commit e55cfac6479bbda902b28103a7bc7d5a90cdc631
parent 9536d411e29aa3f31367f305ef5cee0da8d69771
Author: Vincent Forest <vincent.forest@meso-star.com>
Date: Thu, 22 Feb 2024 14:56:43 +0100
Define a project acronym
Update function names, structure names and file names for the coding
convention and acronym.
Diffstat:
9 files changed, 625 insertions(+), 626 deletions(-)
diff --git a/.gitignore b/.gitignore
@@ -6,5 +6,5 @@
*.txt
.config
tags
-test_*
-!test_*.[ch]
+sadist_*
+!sadist_*.[ch]
diff --git a/Makefile b/Makefile
@@ -18,8 +18,7 @@
include config.mk
-TESTS = test_stardis_probe_boundary
-PROGS = libtriprof.so
+TESTS = sadist_probe_boundary
# Default target
default: .config $(TESTS)
@@ -33,28 +32,27 @@ default: .config $(TESTS)
clean:
rm -f .config sphere.stl sshape.stl scene.txt src/*.o src/*.d
- rm -f $(PROGS) $(TESTS)
+ rm -f libsadist-triprof.so $(TESTS)
-src/prog_trilinear_profile.o:\
+src/sadist_lib_trilinear_profile.o:\
config.mk\
- src/prog_trilinear_profile.c\
- src/stardis_test.h
+ src/sadist.h\
+ src/sadist_lib_trilinear_profile.c
$(CC) $(CFLAGS_SO) $(RSYS_CFLAGS) -c $(@:.o=.c) -o $@
-libtriprof.so: src/prog_trilinear_profile.o
- $(CC) $(CFLAGS_SO) $(RSYS_CFLAGS) -o $@ src/prog_trilinear_profile.o \
+libsadist-triprof.so: src/sadist_lib_trilinear_profile.o
+ $(CC) $(CFLAGS_SO) $(RSYS_CFLAGS) -o $@ src/sadist_lib_trilinear_profile.o \
$(LDFLAGS_SO) $(RSYS_LIBS)
-
-src/test_stardis_probe_boundary.o:\
+src/sadist_probe_boundary.o:\
config.mk\
- src/test_stardis_probe_boundary.c\
- src/stardis_test.h
+ src/sadist.h\
+ src/sadist_probe_boundary.c
$(CC) $(CFLAGS_EXE) $(S3DUT_CFLAGS) $(RSYS_CFLAGS) -c $(@:.o=.c) -o $@
-test_stardis_probe_boundary: src/test_stardis_probe_boundary.o libtriprof.so
+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)
test: $(TESTS)
- ./test_stardis_probe_boundary
+ ./sadist_probe_boundary
diff --git a/README.md b/README.md
@@ -1,6 +1,6 @@
-# Stardis Tests
+# StArDIS Tests
-Set of programs and that test the behavior of the
+Set of programs that test the behavior of the
[Stardis](https://gitlab.com/meso-star/stardis.git) program.
## License
diff --git a/src/prog_trilinear_profile.c b/src/prog_trilinear_profile.c
@@ -1,248 +0,0 @@
-/* Copyright (C) 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 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_test.h"
-
-#include <stardis/stardis-prog-properties.h>
-
-#include <rsys/cstr.h>
-#include <rsys/rsys.h>
-#include <rsys/mem_allocator.h>
-
-#include <stdarg.h> /* va_list */
-#include <getopt.h>
-
-/*******************************************************************************
- * Helper functions
- ******************************************************************************/
-static void
-log_err(const char* msg, ...)
-{
- va_list vargs_list;
- ASSERT(msg);
-
- va_start(vargs_list, msg);
- vfprintf(stderr, msg, vargs_list);
- va_end(vargs_list);
-}
-
-static void
-print_usage(FILE* stream, const char* name)
-{
- fprintf(stream,
-"usage: %s [-h] [-b lower_xyz,upper_xyz]\n"
-" [-t max_Tx,max_Ty,max_Tz]\n",
- name);
-}
-
-static res_T
-parse_spatial_range(struct trilinear_profile* profile, const char* str)
-{
- double range[2] = {0, 0};
- size_t len = 0;
- res_T res = RES_OK;
- ASSERT(profile && str);
-
- res = cstr_to_list_double(str, ',', range, &len, 2);
- if(res == RES_OK && len != 2) res = RES_BAD_ARG;
- if(res != RES_OK) {
- log_err("%s:%lu: unable to parse spatial range parameter `%s' -- %s\n",
- __FILE__, __LINE__, str, res_to_cstr(res));
- goto error;
- }
-
- if(range[0] >= range[1]) {
- log_err("%s:%lu: invalid spatial range [%g, %g]\n",
- __FILE__, __LINE__, range[0], range[1]);
- res = RES_BAD_ARG;
- goto error;
- }
-
- profile->lower[0] = profile->lower[1] = profile->lower[2] = range[0];
- profile->upper[0] = profile->upper[1] = profile->upper[2] = range[1];
-
-exit:
- return res;
-error:
- goto exit;
-}
-
-static res_T
-parse_max_temperatures(struct trilinear_profile* profile, const char* str)
-{
- double abc[3] = {0, 0, 0};
- size_t len = 0;
- res_T res = RES_OK;
- ASSERT(profile && str);
-
- res = cstr_to_list_double(str, ',', abc, &len, 3);
- if(res == RES_OK && len != 3) res = RES_BAD_ARG;
- if(res != RES_OK) {
- log_err("%s:%lu: unable to parse maximum temperatures `%s' -- %s\n",
- __FILE__, __LINE__, str, res_to_cstr(res));
- goto error;
- }
-
- if(abc[0] < 0 || abc[1] < 0 || abc[2] < 0) {
- log_err
- ("%s:%lu: invalid maximum temperatures (X = %g K, Y = %g K, Z = %g K)\n",
- __FILE__, __LINE__, str, abc[0], abc[1], abc[2]);
- res = RES_BAD_ARG;
- goto error;
- }
-
- profile->a[1] = abc[0];
- profile->b[1] = abc[1];
- profile->c[1] = abc[2];
-
-exit:
- return res;
-error:
- goto exit;
-}
-
-static res_T
-parse_args
- (const struct stardis_description_create_context* ctx,
- struct trilinear_profile* profile,
- int argc,
- char* argv[])
-{
- int opt;
- res_T res = RES_OK;
- ASSERT(ctx && profile);
-
- optind = 1;
- while((opt = getopt(argc, argv, "b:ht:")) != -1) {
- switch(opt) {
- case 'b':
- res = parse_spatial_range(profile, optarg);
- if(res != RES_OK) goto error;
- break;
- case 'h':
- print_usage(stdout, ctx->name);
- break;
- case 't':
- res = parse_max_temperatures(profile, optarg);
- if(res != RES_OK) goto error;
- break;
- default: res = RES_BAD_ARG; break;
- }
- }
-
-exit:
- return res;
-error:
- goto exit;
-}
-
-/*******************************************************************************
- * Legal notices
- ******************************************************************************/
-const char*
-get_copyright_notice(void* data)
-{
- (void)data; /* Avoid "unused variable" warnings */
- return "Copyright (C) 2024 |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.";
-}
-
-/*******************************************************************************
- * Create data
- ******************************************************************************/
-void*
-stardis_create_data
- (const struct stardis_description_create_context* ctx,
- void* libdata,
- size_t argc,
- char* argv[])
-{
- struct trilinear_profile* profile = NULL;
- res_T res = RES_OK;
- (void)libdata;
-
- profile = mem_alloc(sizeof(*profile));
- if(!profile) {
- log_err("%s:%lu: error allocating the trilinear profile.\n",
- __FILE__, __LINE__);
- goto error;
- }
-
- *profile = TRILINEAR_PROFILE_NULL;
-
- res = parse_args(ctx, profile, (int)argc, argv);
- if(res != RES_OK) goto error;
-
-exit:
- return profile;
-error:
- if(profile) {
- mem_rm(profile);
- profile = NULL;
- }
- goto exit;
-}
-
-void
-stardis_release_data(void* data)
-{
- ASSERT(data);
- mem_rm(data);
-}
-
-/*******************************************************************************
- * Boundary condition
- ******************************************************************************/
-double
-stardis_boundary_temperature
- (const struct stardis_interface_fragment* frag,
- void* data)
-{
- ASSERT(frag && data);
- return trilinear_profile(data, frag->P);
-}
-
-double*
-stardis_t_range(void* data, double range[2])
-{
- struct trilinear_profile* profile = data;
- ASSERT(data && range);
-
- range[0] = MMIN(profile->a[0], profile->a[1]);
- range[0] = MMIN(MMIN(profile->b[0], profile->b[1]), range[0]);
- range[0] = MMIN(MMIN(profile->c[0], profile->c[1]), range[0]);
-
- range[1] = MMAX(profile->a[0], profile->a[1]);
- range[1] = MMAX(MMAX(profile->b[0], profile->b[1]), range[0]);
- range[1] = MMAX(MMAX(profile->c[0], profile->c[1]), range[0]);
-
- return range;
-}
diff --git a/src/sadist.h b/src/sadist.h
@@ -0,0 +1,89 @@
+/* Copyright (C) 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 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 SADIST_H
+#define SADIST_H
+
+#include <rsys/rsys.h>
+#include <errno.h> /* EINVAL */
+
+struct sadist_trilinear_profile {
+ /* Spatial range in which the trilinear profile is defined */
+ double lower[3];
+ double upper[3];
+
+ double a[2]; /* Interpolated values along X */
+ double b[2]; /* Interpolated values along Y */
+ double c[2]; /* Interpolated values along Z */
+};
+#define SADIST_TRILINEAR_PROFILE_NULL__ {{0,0,0}, {0,0,0}, {0,0}, {0,0}, {0,0}}
+static const struct sadist_trilinear_profile SADIST_TRILINEAR_PROFILE_NULL =
+ SADIST_TRILINEAR_PROFILE_NULL__;
+
+static INLINE int
+sadist_trilinear_profile_check(const struct sadist_trilinear_profile* profile)
+{
+ ASSERT(profile);
+ if(profile->lower[0] >= profile->upper[0]
+ || profile->lower[1] >= profile->upper[1]
+ || profile->lower[2] >= profile->upper[2])
+ return EINVAL;
+
+ return 0;
+}
+
+static INLINE double
+sadist_trilinear_profile
+ (const struct sadist_trilinear_profile* profile,
+ const double p[3])
+{
+ double u, v, w;
+ ASSERT(profile && p);
+ u = (p[0] - profile->lower[0]) / (profile->upper[0] - profile->lower[0]);
+ v = (p[1] - profile->lower[1]) / (profile->upper[1] - profile->lower[1]);
+ w = (p[2] - profile->lower[2]) / (profile->upper[2] - profile->lower[2]);
+ return u * (profile->a[1] - profile->a[0]) + profile->a[0]
+ + v * (profile->b[1] - profile->b[0]) + profile->b[0]
+ + w * (profile->c[1] - profile->c[0]) + profile->c[0];
+}
+
+static INLINE void
+sadist_write_stl
+ (FILE* stream,
+ const double* positions,
+ const size_t nvertices,
+ const size_t* indices,
+ const size_t ntriangles)
+{
+ size_t itri;
+ (void)nvertices;
+
+ fprintf(stream, "solid ascii\n");
+ FOR_EACH(itri, 0, ntriangles) {
+ const double* v0 = positions + indices[itri*3+0]*3;
+ const double* v1 = positions + indices[itri*3+1]*3;
+ const double* v2 = positions + indices[itri*3+2]*3;
+ fprintf(stream, "facet normal 0 1 0\n");
+ fprintf(stream, "\touter loop\n");
+ fprintf(stream, "\t\tvertex %g %g %g\n", SPLIT3(v0));
+ fprintf(stream, "\t\tvertex %g %g %g\n", SPLIT3(v1));
+ fprintf(stream, "\t\tvertex %g %g %g\n", SPLIT3(v2));
+ fprintf(stream, "\tendloop\n");
+ fprintf(stream, "endfacet\n");
+ }
+ fprintf(stream, "endsolid\n");
+}
+
+#endif /* SADIST_H */
diff --git a/src/sadist_lib_trilinear_profile.c b/src/sadist_lib_trilinear_profile.c
@@ -0,0 +1,248 @@
+/* Copyright (C) 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 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 "sadist.h"
+
+#include <stardis/stardis-prog-properties.h>
+
+#include <rsys/cstr.h>
+#include <rsys/rsys.h>
+#include <rsys/mem_allocator.h>
+
+#include <stdarg.h> /* va_list */
+#include <getopt.h>
+
+/*******************************************************************************
+ * Helper functions
+ ******************************************************************************/
+static void
+log_err(const char* msg, ...)
+{
+ va_list vargs_list;
+ ASSERT(msg);
+
+ va_start(vargs_list, msg);
+ vfprintf(stderr, msg, vargs_list);
+ va_end(vargs_list);
+}
+
+static void
+print_usage(FILE* stream, const char* name)
+{
+ fprintf(stream,
+"usage: %s [-h] [-b lower_xyz,upper_xyz]\n"
+" [-t max_Tx,max_Ty,max_Tz]\n",
+ name);
+}
+
+static res_T
+parse_spatial_range(struct sadist_trilinear_profile* profile, const char* str)
+{
+ double range[2] = {0, 0};
+ size_t len = 0;
+ res_T res = RES_OK;
+ ASSERT(profile && str);
+
+ res = cstr_to_list_double(str, ',', range, &len, 2);
+ if(res == RES_OK && len != 2) res = RES_BAD_ARG;
+ if(res != RES_OK) {
+ log_err("%s:%lu: unable to parse spatial range parameter `%s' -- %s\n",
+ __FILE__, __LINE__, str, res_to_cstr(res));
+ goto error;
+ }
+
+ if(range[0] >= range[1]) {
+ log_err("%s:%lu: invalid spatial range [%g, %g]\n",
+ __FILE__, __LINE__, range[0], range[1]);
+ res = RES_BAD_ARG;
+ goto error;
+ }
+
+ profile->lower[0] = profile->lower[1] = profile->lower[2] = range[0];
+ profile->upper[0] = profile->upper[1] = profile->upper[2] = range[1];
+
+exit:
+ return res;
+error:
+ goto exit;
+}
+
+static res_T
+parse_max_temperatures(struct sadist_trilinear_profile* profile, const char* str)
+{
+ double abc[3] = {0, 0, 0};
+ size_t len = 0;
+ res_T res = RES_OK;
+ ASSERT(profile && str);
+
+ res = cstr_to_list_double(str, ',', abc, &len, 3);
+ if(res == RES_OK && len != 3) res = RES_BAD_ARG;
+ if(res != RES_OK) {
+ log_err("%s:%lu: unable to parse maximum temperatures `%s' -- %s\n",
+ __FILE__, __LINE__, str, res_to_cstr(res));
+ goto error;
+ }
+
+ if(abc[0] < 0 || abc[1] < 0 || abc[2] < 0) {
+ log_err
+ ("%s:%lu: invalid maximum temperatures (X = %g K, Y = %g K, Z = %g K)\n",
+ __FILE__, __LINE__, str, abc[0], abc[1], abc[2]);
+ res = RES_BAD_ARG;
+ goto error;
+ }
+
+ profile->a[1] = abc[0];
+ profile->b[1] = abc[1];
+ profile->c[1] = abc[2];
+
+exit:
+ return res;
+error:
+ goto exit;
+}
+
+static res_T
+parse_args
+ (const struct stardis_description_create_context* ctx,
+ struct sadist_trilinear_profile* profile,
+ int argc,
+ char* argv[])
+{
+ int opt;
+ res_T res = RES_OK;
+ ASSERT(ctx && profile);
+
+ optind = 1;
+ while((opt = getopt(argc, argv, "b:ht:")) != -1) {
+ switch(opt) {
+ case 'b':
+ res = parse_spatial_range(profile, optarg);
+ if(res != RES_OK) goto error;
+ break;
+ case 'h':
+ print_usage(stdout, ctx->name);
+ break;
+ case 't':
+ res = parse_max_temperatures(profile, optarg);
+ if(res != RES_OK) goto error;
+ break;
+ default: res = RES_BAD_ARG; break;
+ }
+ }
+
+exit:
+ return res;
+error:
+ goto exit;
+}
+
+/*******************************************************************************
+ * Legal notices
+ ******************************************************************************/
+const char*
+get_copyright_notice(void* data)
+{
+ (void)data; /* Avoid "unused variable" warnings */
+ return "Copyright (C) 2024 |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.";
+}
+
+/*******************************************************************************
+ * Create data
+ ******************************************************************************/
+void*
+stardis_create_data
+ (const struct stardis_description_create_context* ctx,
+ void* libdata,
+ size_t argc,
+ char* argv[])
+{
+ struct sadist_trilinear_profile* profile = NULL;
+ res_T res = RES_OK;
+ (void)libdata;
+
+ profile = mem_alloc(sizeof(*profile));
+ if(!profile) {
+ log_err("%s:%lu: error allocating the trilinear profile.\n",
+ __FILE__, __LINE__);
+ goto error;
+ }
+
+ *profile = SADIST_TRILINEAR_PROFILE_NULL;
+
+ res = parse_args(ctx, profile, (int)argc, argv);
+ if(res != RES_OK) goto error;
+
+exit:
+ return profile;
+error:
+ if(profile) {
+ mem_rm(profile);
+ profile = NULL;
+ }
+ goto exit;
+}
+
+void
+stardis_release_data(void* data)
+{
+ ASSERT(data);
+ mem_rm(data);
+}
+
+/*******************************************************************************
+ * Boundary condition
+ ******************************************************************************/
+double
+stardis_boundary_temperature
+ (const struct stardis_interface_fragment* frag,
+ void* data)
+{
+ ASSERT(frag && data);
+ return sadist_trilinear_profile(data, frag->P);
+}
+
+double*
+stardis_t_range(void* data, double range[2])
+{
+ struct sadist_trilinear_profile* profile = data;
+ ASSERT(data && range);
+
+ range[0] = MMIN(profile->a[0], profile->a[1]);
+ range[0] = MMIN(MMIN(profile->b[0], profile->b[1]), range[0]);
+ range[0] = MMIN(MMIN(profile->c[0], profile->c[1]), range[0]);
+
+ range[1] = MMAX(profile->a[0], profile->a[1]);
+ range[1] = MMAX(MMAX(profile->b[0], profile->b[1]), range[1]);
+ range[1] = MMAX(MMAX(profile->c[0], profile->c[1]), range[1]);
+
+ return range;
+}
diff --git a/src/sadist_probe_boundary.c b/src/sadist_probe_boundary.c
@@ -0,0 +1,272 @@
+/* Copyright (C) 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 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/>. */
+
+#define _POSIX_C_SOURCE 200112L /* popen */
+
+#include "sadist.h"
+
+#include <stardis/stardis-prog-properties.h>
+
+#include <star/s3dut.h>
+
+#include <rsys/double2.h>
+#include <rsys/double3.h>
+#include <rsys/math.h>
+#include <rsys/mem_allocator.h>
+
+#include <errno.h>
+#include <float.h>
+#include <string.h> /* strerror */
+
+/* Axis Aligned Bounding Box */
+struct aabb {
+ double lower[3];
+ double upper[3];
+};
+#define AABB_NULL__ {{DBL_MAX,DBL_MAX,DBL_MAX}, {-DBL_MAX,-DBL_MAX,-DBL_MAX}}
+static const struct aabb AABB_NULL = AABB_NULL__;
+
+/*
+ * 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
+ * forms are immersed in this temperature field: a super shape and a sphere
+ * included in the super shape. On the Monte Carlo side, the temperature is
+ * unknown everywhere except on the surface of the super shape whose
+ * temperature is defined from the aformentionned trilinear profile. We will
+ * estimate the temperature at the sphere boundary at a probe points. We
+ * should find by Monte Carlo the temperature of the trilinear profile at the
+ * position of the probe. It's the test.
+ *
+ * /\ <-- T(x,y,z)
+ * ___/ \___
+ * T(z) \ __ /
+ * | T(y) \ / \ /
+ * |/ T=? *__/ \
+ * o--- T(x) /_ __ _\
+ * \/ \/
+ */
+
+#define FILENAME_SSHAPE "sshape.stl"
+#define FILENAME_SPHERE "sphere.stl"
+#define FILENAME_SCENE "scene.txt"
+
+/* Temperature at the upper bound of the X, Y and Z axis. The temperature at the
+ * lower bound is implicitly 0 K */
+#define TX 333.0 /* [K] */
+#define TY 432.0 /* [K] */
+#define TZ 579.0 /* [K] */
+
+/* Probe position */
+#define PX 1.0
+#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
+
+/*******************************************************************************
+ * Helper functions
+ ******************************************************************************/
+static void
+aabb_update(struct aabb* aabb, const struct s3dut_mesh_data* mesh)
+{
+ size_t ivertex = 0;
+ ASSERT(aabb);
+
+ FOR_EACH(ivertex, 0, mesh->nvertices) {
+ const double* vertex = mesh->positions + ivertex*3;
+ aabb->lower[0] = MMIN(aabb->lower[0], vertex[0]);
+ aabb->lower[1] = MMIN(aabb->lower[1], vertex[1]);
+ aabb->lower[2] = MMIN(aabb->lower[2], vertex[2]);
+ aabb->upper[0] = MMAX(aabb->upper[0], vertex[0]);
+ aabb->upper[1] = MMAX(aabb->upper[1], vertex[1]);
+ aabb->upper[2] = MMAX(aabb->upper[2], vertex[2]);
+ }
+}
+
+static void
+setup_sshape(FILE* stream, struct aabb* aabb)
+{
+ struct s3dut_mesh* sshape = NULL;
+ struct s3dut_mesh_data sshape_data;
+ struct s3dut_super_formula f0 = S3DUT_SUPER_FORMULA_NULL;
+ struct s3dut_super_formula f1 = S3DUT_SUPER_FORMULA_NULL;
+ const double radius = 2;
+ const unsigned nslices = 256;
+
+ f0.A = 1.5; f0.B = 1; f0.M = 11.0; f0.N0 = 1; f0.N1 = 1; f0.N2 = 2.0;
+ f1.A = 1.0; f1.B = 2; f1.M = 3.6; f1.N0 = 1; f1.N1 = 2; f1.N2 = 0.7;
+ S3DUT(create_super_shape(NULL, &f0, &f1, radius, nslices, nslices/2, &sshape));
+ S3DUT(mesh_get_data(sshape, &sshape_data));
+
+ aabb_update(aabb, &sshape_data);
+ sadist_write_stl(stream, sshape_data.positions, sshape_data.nvertices,
+ sshape_data.indices, sshape_data.nprimitives);
+
+ S3DUT(mesh_ref_put(sshape));
+}
+
+static void
+setup_sphere(FILE* stream, struct aabb* aabb)
+{
+ struct s3dut_mesh* sphere = NULL;
+ struct s3dut_mesh_data sphere_data;
+ const double radius = 1;
+ const unsigned nslices = 128;
+
+ S3DUT(create_sphere(NULL, radius, nslices, nslices/2, &sphere));
+ S3DUT(mesh_get_data(sphere, &sphere_data));
+
+ aabb_update(aabb, &sphere_data);
+ sadist_write_stl(stream, sphere_data.positions, sphere_data.nvertices,
+ sphere_data.indices, sphere_data.nprimitives);
+
+ S3DUT(mesh_ref_put(sphere));
+}
+
+static void
+setup_scene
+ (FILE* fp,
+ const char* sshape,
+ const char* sphere,
+ const struct aabb* aabb,
+ struct sadist_trilinear_profile* profile)
+{
+ double low, upp;
+ ASSERT(sshape && sphere && aabb && profile);
+
+ fprintf(fp, "PROGRAM trilinear_profile libsadist-triprof.so\n");
+ fprintf(fp, "SOLID SuperShape 25 7500 500 0.05 0 UNKNOWN 0 BACK %s FRONT %s\n",
+ sshape, sphere);
+ fprintf(fp, "SOLID Sphere 25 7500 500 0.05 0 UNKNOWN 0 BACK %s\n", sphere);
+
+ low = MMIN(MMIN(aabb->lower[0], aabb->lower[1]), aabb->lower[2]);
+ upp = MMAX(MMAX(aabb->upper[0], aabb->upper[1]), aabb->upper[2]);
+ fprintf(fp, "T_BOUNDARY_FOR_SOLID_PROG Dirichlet trilinear_profile %s", sshape);
+ fprintf(fp, " PROG_PARAMS dummy -b %g,%g -t %g,%g,%g\n", low, upp, TX, TY, TZ);
+
+ d3_splat(profile->lower, low);
+ d3_splat(profile->upper, upp);
+ d2(profile->a, 0, TX);
+ d2(profile->b, 0, TY);
+ d2(profile->c, 0, TZ);
+}
+
+static int
+init(struct sadist_trilinear_profile* profile)
+{
+ struct aabb aabb = AABB_NULL;
+ FILE* fp_sshape = NULL;
+ FILE* fp_sphere = NULL;
+ FILE* fp_scene = NULL;
+ int err = 0;
+
+ if((fp_sshape = fopen(FILENAME_SSHAPE, "w")) == NULL) {
+ fprintf(stderr, "Error opening the `"FILENAME_SSHAPE"' file -- %s\n",
+ strerror(errno));
+ err = errno;
+ goto error;
+ }
+ if((fp_sphere = fopen(FILENAME_SPHERE, "w")) == NULL) {
+ fprintf(stderr, "Error opening the `"FILENAME_SPHERE"' file -- %s\n",
+ strerror(errno));
+ err = errno;
+ goto error;
+ }
+ if((fp_scene = fopen(FILENAME_SCENE, "w")) == NULL) {
+ fprintf(stderr, "Error opening the `"FILENAME_SCENE"' file -- %s\n",
+ strerror(errno));
+ err = errno;
+ goto error;
+ }
+
+ setup_sshape(fp_sshape, &aabb);
+ setup_sphere(fp_sphere, &aabb);
+ setup_scene(fp_scene, FILENAME_SSHAPE, FILENAME_SPHERE, &aabb, profile);
+
+exit:
+ if(fp_sshape && fclose(fp_sshape)) { perror("fclose"); if(!err) err = errno; }
+ if(fp_sphere && fclose(fp_sphere)) { perror("fclose"); if(!err) err = errno; }
+ if(fp_scene && fclose(fp_scene)) { perror("fclose"); if(!err) err = errno; }
+ return err;
+error:
+ goto exit;
+}
+
+static int
+run(const struct sadist_trilinear_profile* profile)
+{
+ const double P[3] = {PX, PY, PZ};
+ FILE* output = NULL;
+ double ref = 0;
+ double E = 0;
+ double SE = 0;
+ int n = 0;
+ int err = 0;
+
+ printf(COMMAND"\n");
+
+ if(!(output = popen(COMMAND, "r"))) {
+ fprintf(stderr, "Error executing stardis -- %s\n", strerror(errno));
+ fprintf(stderr, "\t"COMMAND"\n");
+ err = errno;
+ goto error;
+ }
+
+ if((n = fscanf(output, "%lf %lf", &E, &SE)), n != 2 && n != EOF) {
+ fprintf(stderr, "Error reading the output stream -- %s\n", strerror(errno));
+ err = errno;
+ goto error;
+ }
+
+ /* Check command exit status */
+ if((err = pclose(output))) goto error;
+
+ 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:
+ return err;
+error:
+ goto exit;
+}
+
+/*******************************************************************************
+ * The test
+ ******************************************************************************/
+int
+main(int argc, char** argv)
+{
+ struct sadist_trilinear_profile profile = SADIST_TRILINEAR_PROFILE_NULL;
+ int err = 0;
+ (void)argc, (void)argv;
+
+ if((err = init(&profile))) goto error;
+ if((err = run(&profile))) goto error;
+
+exit:
+ if(mem_allocated_size() != 0) {
+ fprintf(stderr, "Memory leaks: %lu bytes\n", mem_allocated_size());
+ if(!err) err = -1;
+ }
+ return err;
+error:
+ goto exit;
+}
diff --git a/src/stardis_test.h b/src/stardis_test.h
@@ -1,87 +0,0 @@
-/* Copyright (C) 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 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 STARDIS_TEST_H
-#define STARDIS_TEST_H
-
-#include <rsys/rsys.h>
-#include <errno.h> /* EINVAL */
-
-struct trilinear_profile {
- /* Spatial range in which the trilinear profile is defined */
- double lower[3];
- double upper[3];
-
- double a[2]; /* Interpolated values along X */
- double b[2]; /* Interpolated values along Y */
- double c[2]; /* Interpolated values along Z */
-};
-#define TRILINEAR_PROFILE_NULL__ {{0,0,0}, {0,0,0}, {0,0}, {0,0}, {0,0}}
-static const struct trilinear_profile TRILINEAR_PROFILE_NULL =
- TRILINEAR_PROFILE_NULL__;
-
-static INLINE int
-check_trilinear_profile(const struct trilinear_profile* profile)
-{
- ASSERT(profile);
- if(profile->lower[0] >= profile->upper[0]
- || profile->lower[1] >= profile->upper[1]
- || profile->lower[2] >= profile->upper[2])
- return EINVAL;
-
- return 0;
-}
-
-static INLINE double
-trilinear_profile(const struct trilinear_profile* profile, const double p[3])
-{
- double u, v, w;
- ASSERT(profile && p);
- u = (p[0] - profile->lower[0]) / (profile->upper[0] - profile->lower[0]);
- v = (p[1] - profile->lower[1]) / (profile->upper[1] - profile->lower[1]);
- w = (p[2] - profile->lower[2]) / (profile->upper[2] - profile->lower[2]);
- return u * (profile->a[1] - profile->a[0]) + profile->a[0]
- + v * (profile->b[1] - profile->b[0]) + profile->b[0]
- + w * (profile->c[1] - profile->c[0]) + profile->c[0];
-}
-
-static INLINE void
-write_stl
- (FILE* stream,
- const double* positions,
- const size_t nvertices,
- const size_t* indices,
- const size_t ntriangles)
-{
- size_t itri;
- (void)nvertices;
-
- fprintf(stream, "solid ascii\n");
- FOR_EACH(itri, 0, ntriangles) {
- const double* v0 = positions + indices[itri*3+0]*3;
- const double* v1 = positions + indices[itri*3+1]*3;
- const double* v2 = positions + indices[itri*3+2]*3;
- fprintf(stream, "facet normal 0 1 0\n");
- fprintf(stream, "\touter loop\n");
- fprintf(stream, "\t\tvertex %g %g %g\n", SPLIT3(v0));
- fprintf(stream, "\t\tvertex %g %g %g\n", SPLIT3(v1));
- fprintf(stream, "\t\tvertex %g %g %g\n", SPLIT3(v2));
- fprintf(stream, "\tendloop\n");
- fprintf(stream, "endfacet\n");
- }
- fprintf(stream, "endsolid\n");
-}
-
-#endif /* STARDIS_TEST_H */
diff --git a/src/test_stardis_probe_boundary.c b/src/test_stardis_probe_boundary.c
@@ -1,273 +0,0 @@
-/* Copyright (C) 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 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/>. */
-
-#define _POSIX_C_SOURCE 200112L /* popen */
-
-#include "stardis_test.h"
-
-#include <stardis/stardis-prog-properties.h>
-
-#include <star/s3dut.h>
-
-#include <rsys/double2.h>
-#include <rsys/double3.h>
-#include <rsys/math.h>
-#include <rsys/mem_allocator.h>
-
-#include <errno.h>
-#include <float.h>
-#include <string.h> /* strerror */
-
-/* Axis Aligned Bounding Box */
-struct aabb {
- double lower[3];
- double upper[3];
-};
-#define AABB_NULL__ {{DBL_MAX,DBL_MAX,DBL_MAX}, {-DBL_MAX,-DBL_MAX,-DBL_MAX}}
-static const struct aabb AABB_NULL = AABB_NULL__;
-
-/*
- * 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
- * forms are immersed in this temperature field: a super shape and a sphere
- * included in the super shape. On the Monte Carlo side, the temperature is
- * unknown everywhere except on the surface of the super shape whose
- * temperature is defined from the aformentionned trilinear profile. We will
- * estimate the temperature at the sphere boundary at a probe points. We
- * should find by Monte Carlo the temperature of the trilinear profile at the
- * position of the probe. It's the test.
- *
- * /\ <-- T(x,y,z)
- * ___/ \___
- * T(z) \ __ /
- * | T(y) \ / \ /
- * |/ T=? *__/ \
- * o--- T(x) /_ __ _\
- * \/ \/
- */
-
-#define FILENAME_SSHAPE "sshape.stl"
-#define FILENAME_SPHERE "sphere.stl"
-#define FILENAME_SCENE "scene.txt"
-
-/* Temperature at the upper bound of the X, Y and Z axis. The temperature at the
- * lower bound is implicitly 0 K */
-#define TX 333.0 /* [K] */
-#define TY 432.0 /* [K] */
-#define TZ 579.0 /* [K] */
-
-/* Probe position */
-#define PX 1.0
-#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
-
-/*******************************************************************************
- * Helper functions
- ******************************************************************************/
-static void
-aabb_update(struct aabb* aabb, const struct s3dut_mesh_data* mesh)
-{
- size_t ivertex = 0;
- ASSERT(aabb);
-
- FOR_EACH(ivertex, 0, mesh->nvertices) {
- const double* vertex = mesh->positions + ivertex*3;
- aabb->lower[0] = MMIN(aabb->lower[0], vertex[0]);
- aabb->lower[1] = MMIN(aabb->lower[1], vertex[1]);
- aabb->lower[2] = MMIN(aabb->lower[2], vertex[2]);
- aabb->upper[0] = MMAX(aabb->upper[0], vertex[0]);
- aabb->upper[1] = MMAX(aabb->upper[1], vertex[1]);
- aabb->upper[2] = MMAX(aabb->upper[2], vertex[2]);
- }
-}
-
-static void
-setup_sshape(FILE* stream, struct aabb* aabb)
-{
- struct s3dut_mesh* sshape = NULL;
- struct s3dut_mesh_data sshape_data;
- struct s3dut_super_formula f0 = S3DUT_SUPER_FORMULA_NULL;
- struct s3dut_super_formula f1 = S3DUT_SUPER_FORMULA_NULL;
- const double radius = 2;
- const unsigned nslices = 256;
-
- f0.A = 1.5; f0.B = 1; f0.M = 11.0; f0.N0 = 1; f0.N1 = 1; f0.N2 = 2.0;
- f1.A = 1.0; f1.B = 2; f1.M = 3.6; f1.N0 = 1; f1.N1 = 2; f1.N2 = 0.7;
- S3DUT(create_super_shape(NULL, &f0, &f1, radius, nslices, nslices/2, &sshape));
- S3DUT(mesh_get_data(sshape, &sshape_data));
-
- aabb_update(aabb, &sshape_data);
- write_stl(stream, sshape_data.positions, sshape_data.nvertices,
- sshape_data.indices, sshape_data.nprimitives);
-
- S3DUT(mesh_ref_put(sshape));
-}
-
-static void
-setup_sphere(FILE* stream, struct aabb* aabb)
-{
- struct s3dut_mesh* sphere = NULL;
- struct s3dut_mesh_data sphere_data;
- const double radius = 1;
- const unsigned nslices = 128;
-
- S3DUT(create_sphere(NULL, radius, nslices, nslices/2, &sphere));
- S3DUT(mesh_get_data(sphere, &sphere_data));
-
- aabb_update(aabb, &sphere_data);
- write_stl(stream, sphere_data.positions, sphere_data.nvertices,
- sphere_data.indices, sphere_data.nprimitives);
-
- S3DUT(mesh_ref_put(sphere));
-}
-
-static void
-setup_scene
- (FILE* fp,
- const char* sshape,
- const char* sphere,
- const struct aabb* aabb,
- struct trilinear_profile* profile)
-{
- double low, upp;
- ASSERT(sshape && sphere && aabb && profile);
-
- fprintf(fp, "PROGRAM trilinear_profile libtriprof.so\n");
- fprintf(fp, "SOLID SuperShape 25 7500 500 0.05 0 UNKNOWN 0 BACK %s FRONT %s\n",
- sshape, sphere);
- fprintf(fp, "SOLID Sphere 25 7500 500 0.05 0 UNKNOWN 0 BACK %s\n", sphere);
-
- low = MMIN(MMIN(aabb->lower[0], aabb->lower[1]), aabb->lower[2]);
- upp = MMAX(MMAX(aabb->upper[0], aabb->upper[1]), aabb->upper[2]);
- fprintf(fp, "T_BOUNDARY_FOR_SOLID_PROG Dirichlet trilinear_profile %s", sshape);
- fprintf(fp, " PROG_PARAMS dummy -b %g,%g -t %g,%g,%g\n", low, upp, TX, TY, TZ);
-
- d3_splat(profile->lower, low);
- d3_splat(profile->upper, upp);
- d2(profile->a, 0, TX);
- d2(profile->b, 0, TY);
- d2(profile->c, 0, TZ);
-
-}
-
-static int
-init(struct trilinear_profile* profile)
-{
- struct aabb aabb = AABB_NULL;
- FILE* fp_sshape = NULL;
- FILE* fp_sphere = NULL;
- FILE* fp_scene = NULL;
- int err = 0;
-
- if((fp_sshape = fopen(FILENAME_SSHAPE, "w")) == NULL) {
- fprintf(stderr, "Error opening the `"FILENAME_SSHAPE"' file -- %s\n",
- strerror(errno));
- err = errno;
- goto error;
- }
- if((fp_sphere = fopen(FILENAME_SPHERE, "w")) == NULL) {
- fprintf(stderr, "Error opening the `"FILENAME_SPHERE"' file -- %s\n",
- strerror(errno));
- err = errno;
- goto error;
- }
- if((fp_scene = fopen(FILENAME_SCENE, "w")) == NULL) {
- fprintf(stderr, "Error opening the `"FILENAME_SCENE"' file -- %s\n",
- strerror(errno));
- err = errno;
- goto error;
- }
-
- setup_sshape(fp_sshape, &aabb);
- setup_sphere(fp_sphere, &aabb);
- setup_scene(fp_scene, FILENAME_SSHAPE, FILENAME_SPHERE, &aabb, profile);
-
-exit:
- if(fp_sshape && fclose(fp_sshape)) { perror("fclose"); if(!err) err = errno; }
- if(fp_sphere && fclose(fp_sphere)) { perror("fclose"); if(!err) err = errno; }
- if(fp_scene && fclose(fp_scene)) { perror("fclose"); if(!err) err = errno; }
- return err;
-error:
- goto exit;
-}
-
-static int
-run(const struct trilinear_profile* profile)
-{
- const double P[3] = {PX, PY, PZ};
- FILE* output = NULL;
- double ref = 0;
- double E = 0;
- double SE = 0;
- int n = 0;
- int err = 0;
-
- printf(COMMAND"\n");
-
- if(!(output = popen(COMMAND, "r"))) {
- fprintf(stderr, "Error executing stardis -- %s\n", strerror(errno));
- fprintf(stderr, "\t"COMMAND"\n");
- err = errno;
- goto error;
- }
-
- if((n = fscanf(output, "%lf %lf", &E, &SE)), n != 2 && n != EOF) {
- fprintf(stderr, "Error reading the output stream -- %s\n", strerror(errno));
- err = errno;
- goto error;
- }
-
- /* Check command exit status */
- if((err = pclose(output))) goto error;
-
- ref = 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:
- return err;
-error:
- goto exit;
-}
-
-/*******************************************************************************
- * The test
- ******************************************************************************/
-int
-main(int argc, char** argv)
-{
- struct trilinear_profile profile = TRILINEAR_PROFILE_NULL;
- int err = 0;
- (void)argc, (void)argv;
-
- if((err = init(&profile))) goto error;
- if((err = run(&profile))) goto error;
-
-exit:
- if(mem_allocated_size() != 0) {
- fprintf(stderr, "Memory leaks: %lu bytes\n", mem_allocated_size());
- if(!err) err = -1;
- }
- return err;
-error:
- goto exit;
-}