commit 202dc45b33773e7111ea6e7ad3ccc6f3b185b10e
parent 5a95ad5edb12d556f0c561d0a2c0d3d48759203d
Author: Vincent Forest <vincent.forest@meso-star.com>
Date: Tue, 14 Dec 2021 11:37:55 +0100
Update the heat path API
When using a picard order greater than 1, a heat path can have branches,
that is, its geometry can be composed of several bands of segments
whereas previously a path was a single and continuous list of segments.
In this commit, the list of strips of the registered paths are now
exposed via the heat path API.
Diffstat:
4 files changed, 241 insertions(+), 86 deletions(-)
diff --git a/src/sdis.h b/src/sdis.h
@@ -1193,24 +1193,32 @@ sdis_green_path_for_each_flux_term
* Heat path API
******************************************************************************/
SDIS_API res_T
-sdis_heat_path_get_vertices_count
+sdis_heat_path_get_status
(const struct sdis_heat_path* path,
- size_t* nvertices);
+ enum sdis_heat_path_flag* status);
SDIS_API res_T
-sdis_heat_path_get_status
+sdis_heat_path_get_line_strips_count
(const struct sdis_heat_path* path,
- enum sdis_heat_path_flag* status);
+ size_t* nstrips);
+
+SDIS_API res_T
+sdis_heat_path_line_strip_get_vertices_count
+ (const struct sdis_heat_path* path,
+ const size_t istrip,
+ size_t* nvertices);
SDIS_API res_T
-sdis_heat_path_get_vertex
+sdis_heat_path_line_strip_get_vertex
(const struct sdis_heat_path* path,
- const size_t ivertex,
+ const size_t istrip,
+ const size_t ivert,
struct sdis_heat_vertex* vertex);
SDIS_API res_T
-sdis_heat_path_for_each_vertex
+sdis_heat_path_line_strip_for_each_vertex
(const struct sdis_heat_path* path,
+ const size_t istrip,
sdis_process_heat_vertex_T func,
void* context);
diff --git a/src/sdis_heat_path.c b/src/sdis_heat_path.c
@@ -34,17 +34,27 @@
#include "sdis_heat_path_conductive_Xd.h"
/*******************************************************************************
- * Exported functions
+ * Local functions
******************************************************************************/
-res_T
-sdis_heat_path_get_vertices_count
- (const struct sdis_heat_path* path, size_t* nvertices)
+/* Return the offset into the list of vertices toward the first vertex of the
+ * line strip */
+static INLINE size_t
+line_strip_vertex_offset(const struct sdis_heat_path* path, const size_t istrip)
{
- if(!path || !nvertices) return RES_BAD_ARG;
- *nvertices = darray_heat_vertex_size_get(&path->vertices);
- return RES_OK;
+ ASSERT(path);
+#ifndef NDEBUG
+ {
+ size_t nstrips;
+ SDIS(heat_path_get_line_strips_count(path, &nstrips));
+ ASSERT(istrip < nstrips);
+ }
+#endif
+ return istrip == 0 ? 0 : darray_size_t_cdata_get(&path->breaks)[istrip-1] + 1;
}
+/*******************************************************************************
+ * Exported functions
+ ******************************************************************************/
res_T
sdis_heat_path_get_status
(const struct sdis_heat_path* path, enum sdis_heat_path_flag* status)
@@ -55,28 +65,112 @@ sdis_heat_path_get_status
}
res_T
-sdis_heat_path_get_vertex
+sdis_heat_path_get_line_strips_count
(const struct sdis_heat_path* path,
- const size_t ivertex,
+ size_t* nstrips)
+{
+ if(!path || !nstrips) return RES_BAD_ARG;
+ /* #strips == #breaks + 1 */
+ *nstrips = darray_size_t_size_get(&path->breaks) + 1;
+ return RES_OK;
+}
+
+res_T
+sdis_heat_path_line_strip_get_vertices_count
+ (const struct sdis_heat_path* path,
+ const size_t istrip,
+ size_t* out_nvertices)
+{
+ size_t nstrips = 0;
+ size_t ivert_begin = 0;
+ size_t ivert_end = 0;
+ res_T res = RES_OK;
+
+ if(!path || !out_nvertices) {
+ res = RES_BAD_ARG;
+ goto error;
+ }
+
+ res = sdis_heat_path_get_line_strips_count(path, &nstrips);
+ if(res != RES_OK) goto error;
+
+ /* Check the indices of the strip */
+ if(istrip >= nstrips) {
+ res = RES_BAD_ARG;
+ goto error;
+ }
+
+ if(istrip == 0) { /* First strip */
+ ivert_begin = 0;
+ } else {
+ ivert_begin = line_strip_vertex_offset(path, istrip);
+ }
+
+ if(istrip == nstrips-1) { /* Last strip */
+ ivert_end = darray_heat_vertex_size_get(&path->vertices) - ivert_begin;
+ } else {
+ ivert_end = line_strip_vertex_offset(path, istrip+1) - ivert_begin;
+ }
+
+ ASSERT(ivert_begin <= ivert_end);
+ *out_nvertices = ivert_end - ivert_begin;
+
+exit:
+ return res;
+error:
+ goto exit;
+}
+
+res_T
+sdis_heat_path_line_strip_get_vertex
+ (const struct sdis_heat_path* path,
+ const size_t istrip,
+ const size_t ivert,
struct sdis_heat_vertex* vertex)
{
- if(!path || !vertex
- || ivertex >= darray_heat_vertex_size_get(&path->vertices)) {
- return RES_BAD_ARG;
+ size_t nverts = 0;
+ size_t ivert_adjusted = 0;
+ res_T res = RES_OK;
+
+ if(!path || !vertex) {
+ res = RES_BAD_ARG;
+ goto error;
}
- *vertex = darray_heat_vertex_cdata_get(&path->vertices)[ivertex];
- return RES_OK;
+ /* By retrieving the number of vertices, we also check the validity of
+ * istrip: the function will return an error if istrip is invalid */
+ res = sdis_heat_path_line_strip_get_vertices_count(path, istrip, &nverts);
+ if(res != RES_OK) goto error;
+
+ if(ivert >= nverts) {
+ res = RES_BAD_ARG;
+ goto error;
+ }
+
+ /* Compute the index into the overall list of vertices */
+ ivert_adjusted = ivert + line_strip_vertex_offset(path, istrip);
+ ASSERT(ivert_adjusted < darray_heat_vertex_size_get(&path->vertices));
+
+ /* Fetch the vertex */
+ *vertex = darray_heat_vertex_cdata_get(&path->vertices)[ivert_adjusted];
+
+exit:
+ return res;
+error:
+ goto exit;
}
res_T
-sdis_heat_path_for_each_vertex
+sdis_heat_path_line_strip_for_each_vertex
(const struct sdis_heat_path* path,
+ const size_t istrip,
sdis_process_heat_vertex_T func,
void* context)
{
- const struct sdis_heat_vertex* vertices;
- size_t i, n;
+ const struct sdis_heat_vertex* vertices = NULL;
+ size_t ivert = 0;
+ size_t offset = 0;
+ size_t nverts = 0;
res_T res = RES_OK;
if(!path || !func) {
@@ -84,10 +178,14 @@ sdis_heat_path_for_each_vertex
goto error;
}
- SDIS(heat_path_get_vertices_count(path, &n));
+ res = sdis_heat_path_line_strip_get_vertices_count(path, istrip, &nverts);
+ if(res != RES_OK) goto error;
+
+ offset = line_strip_vertex_offset(path, istrip);
+
vertices = darray_heat_vertex_cdata_get(&path->vertices);
- FOR_EACH(i, 0, n) {
- res = func(vertices+i, context);
+ FOR_EACH(ivert, 0, nverts) {
+ res = func(vertices+ivert+offset, context);
if(res != RES_OK) goto error;
}
@@ -96,4 +194,3 @@ exit:
error:
goto exit;
}
-
diff --git a/src/test_sdis_solve_probe.c b/src/test_sdis_solve_probe.c
@@ -208,10 +208,10 @@ process_heat_path(const struct sdis_heat_path* path, void* context)
CHK(path && context);
- BA(sdis_heat_path_get_vertices_count(NULL, &n));
- BA(sdis_heat_path_get_vertices_count(path, NULL));
- OK(sdis_heat_path_get_vertices_count(path, &n));
- CHK(n != 0);
+ BA(sdis_heat_path_get_line_strips_count(NULL, &n));
+ BA(sdis_heat_path_get_line_strips_count(path, NULL));
+ OK(sdis_heat_path_get_line_strips_count(path, &n));
+ CHK(n == 1);
BA(sdis_heat_path_get_status(NULL, &status));
BA(sdis_heat_path_get_status(path, NULL));
@@ -224,20 +224,28 @@ process_heat_path(const struct sdis_heat_path* path, void* context)
default: FATAL("Unreachable code.\n"); break;
}
- BA(sdis_heat_path_get_vertex(NULL, 0, &vert));
- BA(sdis_heat_path_get_vertex(path, n, &vert));
- BA(sdis_heat_path_get_vertex(path, 0, NULL));
+ BA(sdis_heat_path_line_strip_get_vertices_count(NULL, 0, &n));
+ BA(sdis_heat_path_line_strip_get_vertices_count(path, 1, &n));
+ BA(sdis_heat_path_line_strip_get_vertices_count(path, 0, NULL));
+ OK(sdis_heat_path_line_strip_get_vertices_count(path, 0, &n));
+ CHK(n != 0);
+
+ BA(sdis_heat_path_line_strip_get_vertex(NULL, 0, 0, &vert));
+ BA(sdis_heat_path_line_strip_get_vertex(path, 1, 1, &vert));
+ BA(sdis_heat_path_line_strip_get_vertex(path, 0, n, &vert));
+ BA(sdis_heat_path_line_strip_get_vertex(path, 0, 0, NULL));
FOR_EACH(i, 0, n) {
- OK(sdis_heat_path_get_vertex(path, i, &vert));
+ OK(sdis_heat_path_line_strip_get_vertex(path, 0, i, &vert));
CHK(vert.type == SDIS_HEAT_VERTEX_CONVECTION
|| vert.type == SDIS_HEAT_VERTEX_CONDUCTION
|| vert.type == SDIS_HEAT_VERTEX_RADIATIVE);
}
- BA(sdis_heat_path_for_each_vertex(NULL, dump_vertex_pos, context));
- BA(sdis_heat_path_for_each_vertex(path, NULL, context));
- OK(sdis_heat_path_for_each_vertex(path, dump_vertex_pos, context));
+ BA(sdis_heat_path_line_strip_for_each_vertex(NULL, 0, dump_vertex_pos, context));
+ BA(sdis_heat_path_line_strip_for_each_vertex(path, 1, dump_vertex_pos, context));
+ BA(sdis_heat_path_line_strip_for_each_vertex(path, 0, NULL, context));
+ OK(sdis_heat_path_line_strip_for_each_vertex(path, 0, dump_vertex_pos, context));
FOR_EACH(i, 0, n-1) {
fprintf(ctx->stream, "l %lu %lu\n",
diff --git a/src/test_sdis_utils.c b/src/test_sdis_utils.c
@@ -178,31 +178,54 @@ solve_green_path(struct sdis_green_path* path, void* ctx)
return RES_OK;
}
+static size_t
+heat_path_get_vertices_count(const struct sdis_heat_path* path)
+{
+ size_t istrip = 0;
+ size_t nstrips = 0;
+ size_t nvertices = 0;
+ CHK(path);
+
+ OK(sdis_heat_path_get_line_strips_count(path, &nstrips));
+ FOR_EACH(istrip, 0, nstrips) {
+ size_t n;
+ OK(sdis_heat_path_line_strip_get_vertices_count(path, istrip, &n));
+ nvertices += n;
+ }
+ return nvertices;
+}
+
static void
-dump_heat_path_position(FILE* stream, const struct sdis_heat_path* path)
+dump_heat_path_positions(FILE* stream, const struct sdis_heat_path* path)
{
- size_t nverts;
- size_t ivert;
+ size_t istrip, nstrips;
+ size_t ivert, nverts;
CHK(stream && path);
- OK(sdis_heat_path_get_vertices_count(path, &nverts));
- FOR_EACH(ivert, 0, nverts) {
- struct sdis_heat_vertex vtx;
- OK(sdis_heat_path_get_vertex(path, ivert, &vtx));
- fprintf(stream, "%g %g %g\n", SPLIT3(vtx.P));
+ OK(sdis_heat_path_get_line_strips_count(path, &nstrips));
+ FOR_EACH(istrip, 0, nstrips) {
+ OK(sdis_heat_path_line_strip_get_vertices_count(path, istrip, &nverts));
+ FOR_EACH(ivert, 0, nverts) {
+ struct sdis_heat_vertex vtx;
+ OK(sdis_heat_path_line_strip_get_vertex(path, istrip, ivert, &vtx));
+ fprintf(stream, "%g %g %g\n", SPLIT3(vtx.P));
+ }
}
}
static void
-dump_heat_path_segments
- (FILE* stream, const struct sdis_heat_path* path, const size_t offset)
+dump_heat_path_line_strip
+ (FILE* stream,
+ const struct sdis_heat_path* path,
+ const size_t istrip,
+ const size_t offset)
{
- size_t nverts, ivert;
+ size_t ivert, nverts;
CHK(stream);
- OK(sdis_heat_path_get_vertices_count(path, &nverts));
+ OK(sdis_heat_path_line_strip_get_vertices_count(path, istrip, &nverts));
fprintf(stream, "%lu", (unsigned long)nverts);
FOR_EACH(ivert, 0, nverts) {
fprintf(stream, " %lu", (unsigned long)(ivert + offset));
@@ -216,29 +239,33 @@ dump_heat_path_vertex_attribs
const struct sdis_heat_path* path,
const enum heat_vertex_attrib attr)
{
- size_t nverts, ivert;
+ size_t ivert, nverts;
+ size_t istrip, nstrips;
CHK(stream && path);
- OK(sdis_heat_path_get_vertices_count(path, &nverts));
- FOR_EACH(ivert, 0, nverts) {
- struct sdis_heat_vertex vtx;
- OK(sdis_heat_path_get_vertex(path, ivert, &vtx));
- switch(attr) {
- case HEAT_VERTEX_WEIGHT:
- fprintf(stream, "%g\n", vtx.weight);
- break;
- case HEAT_VERTEX_TIME:
- fprintf(stream, "%g\n", IS_INF(vtx.time) ? FLT_MAX : vtx.time);
- break;
- case HEAT_VERTEX_TYPE:
- switch(vtx.type) {
- case SDIS_HEAT_VERTEX_CONDUCTION: fprintf(stream, "0.0\n"); break;
- case SDIS_HEAT_VERTEX_CONVECTION: fprintf(stream, "0.5\n"); break;
- case SDIS_HEAT_VERTEX_RADIATIVE: fprintf(stream, "1.0\n"); break;
- default: FATAL("Unreachable code.\n"); break;
- }
- break;
- default: FATAL("Unreachable code.\n"); break;
+ OK(sdis_heat_path_get_line_strips_count(path, &nstrips));
+ FOR_EACH(istrip, 0, nstrips) {
+ OK(sdis_heat_path_line_strip_get_vertices_count(path, istrip, &nverts));
+ FOR_EACH(ivert, 0, nverts) {
+ struct sdis_heat_vertex vtx;
+ OK(sdis_heat_path_line_strip_get_vertex(path, istrip, ivert, &vtx));
+ switch(attr) {
+ case HEAT_VERTEX_WEIGHT:
+ fprintf(stream, "%g\n", vtx.weight);
+ break;
+ case HEAT_VERTEX_TIME:
+ fprintf(stream, "%g\n", IS_INF(vtx.time) ? FLT_MAX : vtx.time);
+ break;
+ case HEAT_VERTEX_TYPE:
+ switch(vtx.type) {
+ case SDIS_HEAT_VERTEX_CONDUCTION: fprintf(stream, "0.0\n"); break;
+ case SDIS_HEAT_VERTEX_CONVECTION: fprintf(stream, "0.5\n"); break;
+ case SDIS_HEAT_VERTEX_RADIATIVE: fprintf(stream, "1.0\n"); break;
+ default: FATAL("Unreachable code.\n"); break;
+ }
+ break;
+ default: FATAL("Unreachable code.\n"); break;
+ }
}
}
}
@@ -306,9 +333,9 @@ dump_heat_paths(FILE* stream, const struct sdis_estimator* estimator)
const struct sdis_heat_path* path;
size_t ipath;
size_t npaths;
+ size_t nstrips_overall;
size_t nvertices;
size_t offset;
- size_t n;
CHK(stream && estimator);
OK(sdis_estimator_get_paths_count(estimator, &npaths));
@@ -320,30 +347,40 @@ dump_heat_paths(FILE* stream, const struct sdis_estimator* estimator)
fprintf(stream, "ASCII\n");
fprintf(stream, "DATASET POLYDATA\n");
- /* Compute the overall number of vertices */
+ /* Compute the overall number of vertices and the overall number of strips */
nvertices = 0;
+ nstrips_overall = 0;
FOR_EACH(ipath, 0, npaths) {
+ size_t n;
OK(sdis_estimator_get_path(estimator, ipath, &path));
- OK(sdis_heat_path_get_vertices_count(path, &n));
- nvertices += n;
+ nvertices += heat_path_get_vertices_count(path);
+ OK(sdis_heat_path_get_line_strips_count(path, &n));
+ nstrips_overall += n;
}
/* Write path positions */
fprintf(stream, "POINTS %lu double\n", (unsigned long)nvertices);
FOR_EACH(ipath, 0, npaths) {
OK(sdis_estimator_get_path(estimator, ipath, &path));
- dump_heat_path_position(stream, path);
+ dump_heat_path_positions(stream, path);
}
/* Write the segment of the paths */
fprintf(stream, "LINES %lu %lu\n",
- (unsigned long)npaths, (unsigned long)(npaths + nvertices));
+ (unsigned long)(nstrips_overall),
+ (unsigned long)(nstrips_overall + nvertices));
offset = 0;
FOR_EACH(ipath, 0, npaths) {
+ size_t path_istrip;
+ size_t path_nstrips;
OK(sdis_estimator_get_path(estimator, ipath, &path));
- dump_heat_path_segments(stream, path, offset);
- OK(sdis_heat_path_get_vertices_count(path, &n));
- offset += n;
+ OK(sdis_heat_path_get_line_strips_count(path, &path_nstrips));
+ FOR_EACH(path_istrip, 0, path_nstrips) {
+ size_t n;
+ dump_heat_path_line_strip(stream, path, path_istrip, offset);
+ OK(sdis_heat_path_line_strip_get_vertices_count(path, path_istrip, &n));
+ offset += n;
+ }
}
fprintf(stream, "POINT_DATA %lu\n", (unsigned long)nvertices);
@@ -377,17 +414,22 @@ dump_heat_paths(FILE* stream, const struct sdis_estimator* estimator)
}
/* Write path type */
- fprintf(stream, "CELL_DATA %lu\n", (unsigned long)npaths);
+ fprintf(stream, "CELL_DATA %lu\n", (unsigned long)nstrips_overall);
fprintf(stream, "SCALARS Path_Type float 1\n");
fprintf(stream, "LOOKUP_TABLE path_type\n");
FOR_EACH(ipath, 0, npaths) {
+ size_t path_istrip;
+ size_t path_nstrips;
enum sdis_heat_path_flag status = SDIS_HEAT_PATH_NONE;
OK(sdis_estimator_get_path(estimator, ipath, &path));
OK(sdis_heat_path_get_status(path, &status));
- switch(status) {
- case SDIS_HEAT_PATH_SUCCESS: fprintf(stream, "0.0\n"); break;
- case SDIS_HEAT_PATH_FAILURE: fprintf(stream, "1.0\n"); break;
- default: FATAL("Unreachable code.\n"); break;
+ OK(sdis_heat_path_get_line_strips_count(path, &path_nstrips));
+ FOR_EACH(path_istrip, 0, path_nstrips) {
+ switch(status) {
+ case SDIS_HEAT_PATH_SUCCESS: fprintf(stream, "0.0\n"); break;
+ case SDIS_HEAT_PATH_FAILURE: fprintf(stream, "1.0\n"); break;
+ default: FATAL("Unreachable code.\n"); break;
+ }
}
}
fprintf(stream, "LOOKUP_TABLE path_type 2\n");