stardis

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

commit fdccf5213deb7e1b161b530d03270dbcdbf7a610
parent 0f168edb13aafd8def9689e6828d5897ba16e4f0
Author: Christophe Coustet <christophe.coustet@meso-star.com>
Date:   Thu, 27 Jan 2022 18:18:18 +0100

Catch-up with stardis-solver API changes, notably path-related API

Diffstat:
Mdoc/stardis-output.5.txt | 54+++++++++++++++++++++++++++++++++++++++---------------
Msrc/stardis-app.c | 9+++++++--
Msrc/stardis-compute.c | 6+++---
Msrc/stardis-output.c | 219+++++++++++++++++++++++++++++++++++++++++++++++++++++++------------------------
Msrc/stardis-output.h | 2+-
Msrc/stardis-solid.c | 2+-
6 files changed, 205 insertions(+), 87 deletions(-)

diff --git a/doc/stardis-output.5.txt b/doc/stardis-output.5.txt @@ -903,7 +903,13 @@ computes a result, some of the heat paths (successful paths, erroneous paths, or both) sampled during the simulation are written to files. Each path is written in VTK [1] format, one VTK file per path. The path description can include vertices' time if it makes sense, that is if the computation time is -not INF. +not INF. Due to the branching nature of non-linear Monte-Carlo algorithms, +paths are made of strips. Whith a Picard order of 1, there is only a single +strip, with higher orders, the number of strips can be greater than 1. As a +result, the whole path is a tree: past the first strip, each strip can start +from any vertex of one of the previous strips. This tree, when displaying the +*Branch_id* field, starts with id 0, then increments each time a non-linearity +leads to the creation of a new strip (to fetch a temperature). [verse] _______ @@ -914,31 +920,41 @@ _______ "DATASET POLYDATA" "POINTS" #vertices "double" <path-vertices> - "LINES 1" #vertices+1 - <heat-path> + "LINES" #strips #vertices+#strips + <heat-strips> + "CELL_DATA" #strips + "SCALAR Path_Failure unsigned_char 1" + "LOOKUP_TABLE default" + <path-failures> "POINT_DATA" #vertices "SCALARS Vertex_Type unsigned_char 1" "LOOKUP_TABLE default" <vertices-types> - "CELL_DATA 1" - "SCALAR Path_type unsigned_char 1" - "LOOKUP_TABLE default" - <path-type> "SCALARS Weight double 1" "LOOKUP_TABLE default" - <weigths> + <weights> + "SCALARS Branch_id int 1" + "LOOKUP_TABLE default" + <branch_ids> [ <vertices-time> ] # if not steady <path-vertices> ::= <real3> <path-vertices> # #vertices vertices -<heat-path> ::= #vertices "0" "1" ... #vertices-1 +<path-failures> ::= <path-failure> + <path-failures> # #strips failure statutes + +<heat-strips> ::= <heat-strip> + <heat-strips> # #strips strips <vertices-types> ::= <vertice-type> <vertices-types> # #vertices types -<weigths> ::= REAL - <weigths> # #vertices weigths +<weights> ::= <weight> + <weights> # #vertices weights + +<branch_ids> ::= <branch_id> + <branch_ids> # #vertices ids <vertices-time> ::= "SCALARS Time double 1" "LOOKUP_TABLE default" @@ -948,15 +964,23 @@ _______ <real3> ::= REAL REAL REAL -<durations> ::= REAL # in [0, INF) - <durations> # #vertices durations +<path-failure> ::= "0" # SUCCESS + | "1" # FAILURE + +<heat-strip> ::= #strip_vertices <vtx_idx 1> ... <vtx_idx #strip_vertices> <vertice-type> ::= "0" # CONDUCTION | "1" # CONVECTION | "2" # RADIATIVE -<path-type> ::= "0" # SUCCESS - | "1" # FAILURE +<weight> ::= REAL + +<branch-id> ::= INTEGER in [0 Picard_Order] + +<durations> ::= REAL # in [0, INF) + <durations> # #vertices durations + +<vtx_idx> ::= INTEGER # in [0 #vertices[ _______ diff --git a/src/stardis-app.c b/src/stardis-app.c @@ -210,6 +210,7 @@ stardis_init struct str str; unsigned i, vcount, tcount, ocount, count; int is_for_compute; + struct sdis_device_create_args dev_args; ASSERT(args && logger && allocator && stardis); @@ -261,8 +262,12 @@ stardis_init is_for_compute = (stardis->mode & COMPUTE_MODES) && !(stardis->mode & MODE_DUMP_VTK); - ERR(sdis_device_create(stardis->logger, stardis->allocator, stardis->nthreads, - args->verbose, &stardis->dev)); + dev_args.logger = stardis->logger; + dev_args.allocator = stardis->allocator; + dev_args.nthreads_hint = stardis->nthreads; + dev_args.verbosity = stardis->verbose; + dev_args.use_mpi = 0; /* No MPI yet */ + ERR(sdis_device_create(&dev_args, &stardis->dev)); ERR(init_geometry(stardis->logger, stardis->allocator, stardis->verbose, &stardis->geometry)); diff --git a/src/stardis-compute.c b/src/stardis-compute.c @@ -849,8 +849,8 @@ compute_camera(struct stardis* stardis, struct time* start) args.cam = cam; d2_set(args.time_range, stardis->camera.time_range); - args.image_resolution[0] = width; - args.image_resolution[1] = height; + args.image_definition[0] = width; + args.image_definition[1] = height; args.spp = (size_t)stardis->camera.spp; args.register_paths = stardis->dump_paths; args.picard_order = stardis->picard_order; @@ -1210,7 +1210,7 @@ compute_map(struct stardis* stardis, struct time* start) ERR(sdis_solve_boundary(stardis->sdis_scn, &args, darray_estimators_data_get(&estimators) + p)); } - dump_map(stardis, &estimators, stdout); + ERR(dump_map(stardis, &estimators, stdout)); end: if(estimators_initialized) { diff --git a/src/stardis-output.c b/src/stardis-output.c @@ -165,8 +165,8 @@ dump_path FILE* stream = NULL; char* name = NULL; enum sdis_heat_path_flag status = SDIS_HEAT_PATH_NONE; - size_t vcount_, name_sz; - unsigned long i, vcount; + size_t vcount_, scount_, offset, name_sz, istrip; + unsigned long scount, vcount; ASSERT(path && dump_ctx && dump_ctx->stardis @@ -189,67 +189,121 @@ dump_path res = RES_IO_ERR; goto error; } + + /* Get counts */ + ERR(sdis_heat_path_get_line_strips_count(path, &scount_)); + if(scount > ULONG_MAX) goto abort; + scount = (unsigned long)scount_; + vcount_ = 0; + FOR_EACH(istrip, 0, scount_) { + size_t n; + ERR(sdis_heat_path_line_strip_get_vertices_count(path, istrip, &n)); + vcount_+= n; + } + if(vcount > ULONG_MAX) goto abort; + vcount = (unsigned long)vcount_; /* Header */ fprintf(stream, "# vtk DataFile Version 2.0\n"); fprintf(stream, "Heat path\n"); fprintf(stream, "ASCII\n"); fprintf(stream, "DATASET POLYDATA\n"); /* Write path positions */ - sdis_heat_path_get_vertices_count(path, &vcount_); - ASSERT(vcount_ < ULONG_MAX); - vcount = (unsigned long)vcount_; fprintf(stream, "POINTS %lu double\n", vcount); - FOR_EACH(i, 0, vcount) { - struct sdis_heat_vertex vtx; - ERR(sdis_heat_path_get_vertex(path, i, &vtx)); - fprintf(stream, "%g %g %g\n", SPLIT3(vtx.P)); - } - /* Write the segment of the path */ - fprintf(stream, "LINES %d %lu\n", 1, 1 + vcount); - fprintf(stream, "%lu", vcount); - FOR_EACH(i, 0, vcount) fprintf(stream, " %lu", i); - fprintf(stream, "\n"); - - /* Write path type */ - fprintf(stream, "CELL_DATA %d\n", 1); - fprintf(stream, "SCALARS Path_Type unsigned_char 1\n"); - fprintf(stream, "LOOKUP_TABLE default\n"); - switch (status) { - case SDIS_HEAT_PATH_SUCCESS: fprintf(stream, "0\n"); break; - case SDIS_HEAT_PATH_FAILURE: fprintf(stream, "1\n"); break; - default: FATAL("Unreachable code.\n"); break; + FOR_EACH(istrip, 0, scount_) { + size_t ivert, nverts; + ERR(sdis_heat_path_line_strip_get_vertices_count(path, istrip, &nverts)); + FOR_EACH(ivert, 0, nverts) { + struct sdis_heat_vertex vtx; + ERR(sdis_heat_path_line_strip_get_vertex(path, istrip, ivert, &vtx)); + fprintf(stream, "%g %g %g\n", SPLIT3(vtx.P)); + } + } + /* Write the strips of the path */ + fprintf(stream, "LINES %lu %lu\n", scount, scount + vcount); + offset = 0; + FOR_EACH(istrip, 0, scount) { + size_t ivert, nverts; + ERR(sdis_heat_path_line_strip_get_vertices_count(path, istrip, &nverts)); + if(nverts > ULONG_MAX) goto abort; + fprintf(stream, "%lu", (unsigned long)nverts); + FOR_EACH(ivert, 0, nverts) { + if(ivert + offset > ULONG_MAX) goto abort; + fprintf(stream, " %lu", (unsigned long)(ivert + offset)); + } + fprintf(stream, "\n"); + offset += nverts; } + /* Write path status on strips */ + fprintf(stream, "CELL_DATA %lu\n", scount); + fprintf(stream, "SCALARS Path_Failure unsigned_char 1\n"); + fprintf(stream, "LOOKUP_TABLE default\n"); + FOR_EACH(istrip, 0, scount) { + switch (status) { + case SDIS_HEAT_PATH_SUCCESS: fprintf(stream, "0\n"); break; + case SDIS_HEAT_PATH_FAILURE: fprintf(stream, "1\n"); break; + default: FATAL("Unreachable code.\n"); break; + } + } fprintf(stream, "POINT_DATA %lu\n", vcount); /* Write the type of the random walk vertices */ fprintf(stream, "SCALARS Vertex_Type unsigned_char 1\n"); fprintf(stream, "LOOKUP_TABLE default\n"); - FOR_EACH(i, 0, vcount) { - struct sdis_heat_vertex vtx; - ERR(sdis_heat_path_get_vertex(path, i, &vtx)); - ASSERT((size_t)vtx.type <= UCHAR_MAX); - fprintf(stream, "%d\n", vtx.type); + FOR_EACH(istrip, 0, scount_) { + size_t ivert, nverts; + ERR(sdis_heat_path_line_strip_get_vertices_count(path, istrip, &nverts)); + FOR_EACH(ivert, 0, nverts) { + struct sdis_heat_vertex vtx; + ERR(sdis_heat_path_line_strip_get_vertex(path, istrip, ivert, &vtx)); + if((size_t)vtx.type > UCHAR_MAX) goto abort; + switch(vtx.type) { + case SDIS_HEAT_VERTEX_CONDUCTION: fprintf(stream, "%d\n", 0); break; + case SDIS_HEAT_VERTEX_CONVECTION: fprintf(stream, "%d\n", 1); break; + case SDIS_HEAT_VERTEX_RADIATIVE: fprintf(stream, "%d\n", 2); break; + default: FATAL("Unreachable code.\n"); break; + } + } } /* Write the weights of the random walk vertices */ fprintf(stream, "SCALARS Weight double 1\n"); fprintf(stream, "LOOKUP_TABLE default\n"); - FOR_EACH(i, 0, vcount) { - struct sdis_heat_vertex vtx; - ERR(sdis_heat_path_get_vertex(path, i, &vtx)); - fprintf(stream, "%g\n", vtx.weight); + FOR_EACH(istrip, 0, scount_) { + size_t ivert, nverts; + ERR(sdis_heat_path_line_strip_get_vertices_count(path, istrip, &nverts)); + FOR_EACH(ivert, 0, nverts) { + struct sdis_heat_vertex vtx; + ERR(sdis_heat_path_line_strip_get_vertex(path, istrip, ivert, &vtx)); + fprintf(stream, "%g\n", vtx.weight); + } } - /* If computation time is not INF for every vertex, + /* Write the branch_id of the random walk vertices */ + fprintf(stream, "SCALARS Branch_id int 1\n"); + fprintf(stream, "LOOKUP_TABLE default\n"); + FOR_EACH(istrip, 0, scount_) { + size_t ivert, nverts; + ERR(sdis_heat_path_line_strip_get_vertices_count(path, istrip, &nverts)); + FOR_EACH(ivert, 0, nverts) { + struct sdis_heat_vertex vtx; + ERR(sdis_heat_path_line_strip_get_vertex(path, istrip, ivert, &vtx)); + fprintf(stream, "%d\n", vtx.branch_id); + } + } + /* If computation time is not INF, * write the time of the random walk vertices */ - FOR_EACH(i, 0, vcount) { - struct sdis_heat_vertex vtx; - ERR(sdis_heat_path_get_vertex(path, i, &vtx)); - if(i == 0) { - if(IS_INF(vtx.time)) break; - fprintf(stream, "SCALARS Time double 1\n"); - fprintf(stream, "LOOKUP_TABLE default\n"); + FOR_EACH(istrip, 0, scount_) { + size_t ivert, nverts; + ERR(sdis_heat_path_line_strip_get_vertices_count(path, istrip, &nverts)); + FOR_EACH(ivert, 0, nverts) { + struct sdis_heat_vertex vtx; + ERR(sdis_heat_path_line_strip_get_vertex(path, istrip, ivert, &vtx)); + if(istrip == 0 && ivert == 0) { + if(IS_INF(vtx.time)) break; + fprintf(stream, "SCALARS Time double 1\n"); + fprintf(stream, "LOOKUP_TABLE default\n"); + } + if(IS_INF(vtx.time)) goto abort; + fprintf(stream, "%g\n", vtx.time); } - ASSERT(!IS_INF(vtx.time)); - fprintf(stream, "%g\n", vtx.time); } end: @@ -258,6 +312,9 @@ end: return res; error: goto end; +abort: + res = RES_BAD_ARG; + goto error; } res_T @@ -273,7 +330,7 @@ dump_vtk_image ASSERT(buf && stream); ERR(sdis_estimator_buffer_get_definition(buf, def)); - ASSERT(def[0] != 0 && def[1] != 0 && def[0] * def[1] <= ULONG_MAX); + if(def[0] == 0 || def[1] == 0 || def[0] * def[1] > ULONG_MAX) goto abort; definition[0] = (unsigned long)def[0]; definition[1] = (unsigned long)def[1]; @@ -344,7 +401,7 @@ dump_vtk_image size_t nfails; ERR(sdis_estimator_buffer_at(buf, ix, iy, &estimator)); ERR(sdis_estimator_get_failure_count(estimator, &nfails)); - ASSERT(nfails <= ULONG_MAX); + if(nfails > ULONG_MAX) goto abort; fprintf(stream, "%lu\n", (unsigned long)nfails); } } @@ -354,6 +411,9 @@ end: return res; error: goto end; +abort: + res = RES_BAD_ARG; + goto error; } res_T @@ -368,7 +428,7 @@ dump_ht_image ASSERT(buf && stream); ERR(sdis_estimator_buffer_get_definition(buf, def)); - ASSERT(def[0] <= ULONG_MAX && def[1] <= ULONG_MAX); + if(def[0] > ULONG_MAX || def[1] > ULONG_MAX) goto abort; definition[0] = (unsigned long)def[0]; definition[1] = (unsigned long)def[1]; @@ -390,6 +450,9 @@ end: return res; error: goto end; +abort: + res = RES_BAD_ARG; + goto error; } #define FW(Ptr, Count) \ @@ -441,7 +504,7 @@ dump_sample_end ERR(sdis_green_path_get_end_type(path, &end_type)); if(end_type == SDIS_GREEN_PATH_END_RADIATIVE) { size_t trad_id = darray_descriptions_size_get(e_ctx->desc); - ASSERT(trad_id <= UINT_MAX); + if(trad_id > UINT_MAX) goto abort; /* End, End ID, X, Y, Z, Elapsed time */ fprintf(stream, "TRAD, %u, 0, 0, 0, %g\n", (unsigned)trad_id, elapsed); @@ -473,7 +536,7 @@ dump_sample_end if(pt.data.mdmvert.vertex.P[0] == INF) { /* Radiative output (Trad) */ size_t sz = darray_descriptions_size_get(e_ctx->desc); - ASSERT(sz <= UINT_MAX); + if(sz > UINT_MAX) goto abort; id = (unsigned)sz; /* Trad ID */ } else if(type == SDIS_FLUID) { @@ -497,6 +560,9 @@ end: return res; error: goto end; +abort: + res = RES_BAD_ARG; + goto error; } static res_T @@ -520,7 +586,7 @@ dump_sample ERR(sdis_green_path_get_end_type(path, &end_type)); if(end_type == SDIS_GREEN_PATH_END_RADIATIVE) { size_t trad_id = darray_descriptions_size_get(w_ctx->desc); - ASSERT(trad_id <= UINT_MAX); + if(trad_id > UINT_MAX) goto abort; header.at_initial = 0; header.id = (unsigned)trad_id; } else { @@ -559,7 +625,7 @@ dump_sample if(pt.data.mdmvert.vertex.P[0] == INF) { /* Radiative output (Trad) */ sz = darray_descriptions_size_get(w_ctx->desc); - ASSERT(sz <= UINT_MAX); + if(sz > UINT_MAX) goto abort; header.id = (unsigned)sz; /* Trad ID */ } else if(type == SDIS_FLUID) { @@ -582,10 +648,10 @@ dump_sample ERR(sdis_green_path_for_each_power_term(path, merge_power_terms, w_ctx)); ERR(sdis_green_path_for_each_flux_term(path, merge_flux_terms, w_ctx)); sz = htable_weigth_size_get(&w_ctx->pw); - ASSERT(sz <= UINT_MAX); + if(sz > UINT_MAX) goto abort; header.pcount = (unsigned)sz; sz = htable_weigth_size_get(&w_ctx->flux); - ASSERT(sz <= UINT_MAX); + if(sz > UINT_MAX) goto abort; header.fcount = (unsigned)sz; /* Write path's header */ @@ -635,6 +701,9 @@ end: return res; error: goto end; +abort: + res = RES_BAD_ARG; + goto error; } res_T @@ -667,7 +736,7 @@ dump_green_bin ERR(sdis_green_function_get_paths_count(green, &ok_count)); ERR(sdis_green_function_get_invalid_paths_count(green, &failed_count)); sz = darray_descriptions_size_get(&stardis->descriptions); - ASSERT(sz <= UINT_MAX); + if(sz > UINT_MAX) goto abort; szd = (unsigned)sz; ASSERT(szd == (stardis->counts.smed_count + stardis->counts.fmed_count @@ -681,7 +750,7 @@ dump_green_bin const struct description* desc = descs + i; const struct str* name = get_description_name(desc); const size_t len = str_len(name); - ASSERT(name_pool_sz + len + 1 <= UINT_MAX); + if(name_pool_sz + len + 1 > UINT_MAX) goto abort; name_pool_sz += (unsigned)(len + 1); } pool_ptr = name_pool = MEM_ALLOC(stardis->allocator, name_pool_sz); @@ -746,6 +815,9 @@ end: return res; error: goto end; +abort: + res = RES_BAD_ARG; + goto error; } res_T @@ -825,7 +897,7 @@ print_sample if(pt.data.mdmvert.vertex.P[0] == INF) { /* Radiative output (Trad)*/ size_t sz = darray_descriptions_size_get(w_ctx->desc); - ASSERT(sz <= UINT_MAX); + if(sz > UINT_MAX) goto abort; fprintf(w_ctx->stream, "R\t%u", (unsigned)sz); } else if(type == SDIS_FLUID) { @@ -856,7 +928,7 @@ print_sample ERR(sdis_green_path_for_each_flux_term(path, merge_flux_terms, w_ctx)); fcount = htable_weigth_size_get(&w_ctx->flux); - ASSERT(pcount <= ULONG_MAX && fcount <= ULONG_MAX); + if(pcount > ULONG_MAX || fcount > ULONG_MAX) goto abort; fprintf(w_ctx->stream, "\t%lu\t%lu", (unsigned long)pcount, (unsigned long)fcount); @@ -883,6 +955,9 @@ end: return res; error: goto end; +abort: + res = RES_BAD_ARG; + goto error; } res_T @@ -902,13 +977,13 @@ dump_green_ascii ASSERT(green && stardis && stream); ERR(sdis_green_function_get_paths_count(green, &sz)); - ASSERT(sz <= UINT_MAX); + if(sz > UINT_MAX) goto abort; ok_count = (unsigned)sz; ERR(sdis_green_function_get_invalid_paths_count(green, &sz)); - ASSERT(sz <= UINT_MAX); + if(sz > UINT_MAX) goto abort; failed_count = (unsigned)sz; sz = darray_descriptions_size_get(&stardis->descriptions); - ASSERT(sz <= UINT_MAX); + if(sz > UINT_MAX) goto abort; szd = (unsigned)sz; descs = darray_descriptions_cdata_get(&stardis->descriptions); @@ -1044,6 +1119,9 @@ end: return res; error: goto end; +abort: + res = RES_BAD_ARG; + goto error; } res_T @@ -1390,7 +1468,7 @@ print_single_MC_result /* Fetch the estimation data */ ERR(sdis_estimator_get_temperature(estimator, &result)); ERR(sdis_estimator_get_failure_count(estimator, &nfailures_)); - ASSERT(nfailures_ <= ULONG_MAX && stardis->samples <= ULONG_MAX); + if(nfailures_ > ULONG_MAX || stardis->samples > ULONG_MAX) goto abort; nfailures = (unsigned long)nfailures_; nsamples = (unsigned long)stardis->samples; if(nfailures == nsamples) { @@ -1570,14 +1648,18 @@ end: return res; error: goto end; +abort: + res = RES_BAD_ARG; + goto error; } -void +res_T dump_map (const struct stardis* stardis, const struct darray_estimators* estimators, FILE* stream) { + res_T res = RES_OK; unsigned i, vcount, tcount, last_v = 0; const size_t* idx; size_t sz; @@ -1589,7 +1671,7 @@ dump_map est = darray_estimators_cdata_get(estimators); idx = darray_size_t_cdata_get(&stardis->compute_surface.primitives); sz = darray_size_t_size_get(&stardis->compute_surface.primitives); - ASSERT(sz <= UINT_MAX); + if(sz > UINT_MAX) goto abort; szp = (unsigned)sz; SG3D(geometry_get_unique_vertices_count(stardis->geometry.sg3d, &vcount)); SG3D(geometry_get_unique_triangles_count(stardis->geometry.sg3d, &tcount)); @@ -1598,7 +1680,7 @@ dump_map for(i = 0; i < szp; ++i) { unsigned t; unsigned indices[3]; - ASSERT(idx[i] <= UINT_MAX); + if(idx[i] > UINT_MAX) goto abort; t = (unsigned)idx[i]; SG3D(geometry_get_unique_triangle_vertices(stardis->geometry.sg3d, t, indices)); @@ -1621,7 +1703,7 @@ dump_map for(i = 0; i < szp; ++i) { unsigned t; unsigned indices[3]; - ASSERT(idx[i] <= UINT_MAX); + if(idx[i] > UINT_MAX) goto abort; t = (unsigned)idx[i]; SG3D(geometry_get_unique_triangle_vertices(stardis->geometry.sg3d, t, indices)); @@ -1647,7 +1729,7 @@ dump_map for(i = 0; i < szp; ++i) { size_t nfails; SDIS(estimator_get_failure_count(est[i], &nfails)); - ASSERT(nfails <= UINT_MAX); + if(nfails > UINT_MAX) goto abort; fprintf(stream, "%u\n", (unsigned)nfails); } fprintf(stream, "SCALARS computation_time_estimate float 1\n"); @@ -1664,6 +1746,13 @@ dump_map SDIS(estimator_get_realisation_time(est[i], &time)); fprintf(stream, "%f\n", time.SE); } +end: + return res; +error: + goto end; +abort: + res = RES_BAD_ARG; + goto error; } res_T diff --git a/src/stardis-output.h b/src/stardis-output.h @@ -97,7 +97,7 @@ print_single_MC_result struct stardis* stardis, FILE* stream); -extern void +extern res_T dump_map (const struct stardis* stardis, const struct darray_estimators* estimators, diff --git a/src/stardis-solid.c b/src/stardis-solid.c @@ -131,7 +131,7 @@ create_solver_solid solid_shader.calorific_capacity = solid_get_calorific_capacity; solid_shader.thermal_conductivity = solid_get_thermal_conductivity; solid_shader.volumic_mass = solid_get_volumic_mass; - solid_shader.delta_solid = solid_get_delta; + solid_shader.delta = solid_get_delta; #if Stardis_VERSION_MINOR == 3 solid_shader.delta_boundary = solid_get_delta_boundary; #endif