sdis_misc.h (5004B)
1 /* Copyright (C) 2016-2025 |Méso|Star> (contact@meso-star.com) 2 * 3 * This program is free software: you can redistribute it and/or modify 4 * it under the terms of the GNU General Public License as published by 5 * the Free Software Foundation, either version 3 of the License, or 6 * (at your option) any later version. 7 * 8 * This program is distributed in the hope that it will be useful, 9 * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 * GNU General Public License for more details. 12 * 13 * You should have received a copy of the GNU General Public License 14 * along with this program. If not, see <http://www.gnu.org/licenses/>. */ 15 16 #ifndef SDIS_MISC_H 17 #define SDIS_MISC_H 18 19 #include "sdis_heat_path.h" 20 21 #include <rsys/float2.h> 22 #include <rsys/float3.h> 23 #include <star/ssp.h> 24 25 struct bound_flux_result { 26 double Tradiative; 27 double Tboundary; 28 double Tfluid; 29 }; 30 #define BOUND_FLUX_RESULT_NULL__ {0,0,0} 31 static const struct bound_flux_result 32 BOUND_FLUX_RESULT_NULL = BOUND_FLUX_RESULT_NULL__; 33 34 struct accum { 35 double sum; /* Sum of MC weights */ 36 double sum2; /* Sum of square MC weights */ 37 size_t count; /* #accumulated MC weights */ 38 }; 39 #define ACCUM_NULL__ {0,0,0} 40 static const struct accum ACCUM_NULL = ACCUM_NULL__; 41 42 /* Empirical scale factor to apply to the upper bound of the ray range in order 43 * to handle numerical imprecisions */ 44 #define RAY_RANGE_MAX_SCALE 1.001f 45 46 /* Define a new result code from RES_BAD_OP saying that the bad operation is 47 * definitive, i.e. in the current state, the realisation will inevitably fail. 48 * It is thus unecessary to retry a specific section of the random walk */ 49 #define RES_BAD_OP_IRRECOVERABLE (-RES_BAD_OP) 50 51 #define BOLTZMANN_CONSTANT 5.6696e-8 /* W/m^2/K^4 */ 52 53 static INLINE void 54 sum_accums 55 (const struct accum accums[], 56 const size_t naccums, 57 struct accum* accum) 58 { 59 struct accum acc = ACCUM_NULL; 60 size_t i; 61 ASSERT(accums && naccums && accum); 62 63 FOR_EACH(i, 0, naccums) { 64 acc.sum += accums[i].sum; 65 acc.sum2 += accums[i].sum2; 66 acc.count += accums[i].count; 67 } 68 *accum = acc; 69 } 70 71 /* Reflect the V wrt the normal N. By convention V points outward the surface */ 72 static FINLINE float* 73 reflect_2d(float res[2], const float V[2], const float N[2]) 74 { 75 float tmp[2]; 76 float cos_V_N; 77 ASSERT(res && V && N); 78 ASSERT(f2_is_normalized(V) && f2_is_normalized(N)); 79 cos_V_N = f2_dot(V, N); 80 f2_mulf(tmp, N, 2*cos_V_N); 81 f2_sub(res, tmp, V); 82 return res; 83 } 84 85 /* Reflect the V wrt the normal N. By convention V points outward the surface */ 86 static FINLINE float* 87 reflect_3d(float res[3], const float V[3], const float N[3]) 88 { 89 float tmp[3]; 90 float cos_V_N; 91 ASSERT(res && V && N); 92 ASSERT(f3_is_normalized(V) && f3_is_normalized(N)); 93 cos_V_N = f3_dot(V, N); 94 f3_mulf(tmp, N, 2*cos_V_N); 95 f3_sub(res, tmp, V); 96 f3_normalize(res, res); /* Handle numerical issue */ 97 return res; 98 } 99 100 static FINLINE double* 101 move_pos_2d(double pos[2], const float dir[2], const float delta) 102 { 103 ASSERT(pos && dir); 104 pos[0] += dir[0] * delta; 105 pos[1] += dir[1] * delta; 106 return pos; 107 } 108 109 static FINLINE double* 110 move_pos_3d(double pos[3], const float dir[3], const float delta) 111 { 112 ASSERT(pos && dir); 113 pos[0] += dir[0] * delta; 114 pos[1] += dir[1] * delta; 115 pos[2] += dir[2] * delta; 116 return pos; 117 } 118 119 static INLINE double 120 sample_time(struct ssp_rng* rng, const double time_range[2]) 121 { 122 ASSERT(time_range && time_range[0] >= 0 && time_range[1] >= time_range[0]); 123 ASSERT(rng); 124 if(time_range[0] == time_range[1]) return time_range[0]; 125 return ssp_rng_uniform_double(rng, time_range[0], time_range[1]); 126 } 127 128 static INLINE res_T 129 register_heat_vertex 130 (struct sdis_heat_path* path, 131 const struct sdis_rwalk_vertex* vtx, 132 const double weight, 133 const enum sdis_heat_vertex_type type, 134 const int branch_id) 135 { 136 struct sdis_heat_vertex heat_vtx = SDIS_HEAT_VERTEX_NULL; 137 ASSERT(vtx && branch_id >= 0); 138 139 if(!path) return RES_OK; 140 141 heat_vtx.P[0] = vtx->P[0]; 142 heat_vtx.P[1] = vtx->P[1]; 143 heat_vtx.P[2] = vtx->P[2]; 144 heat_vtx.time = vtx->time; 145 heat_vtx.weight = weight; 146 heat_vtx.type = type; 147 heat_vtx.branch_id = branch_id; 148 return heat_path_add_vertex(path, &heat_vtx); 149 } 150 151 extern LOCAL_SYM res_T 152 time_rewind 153 (struct sdis_scene* scn, 154 const double mu, 155 const double t0, /* Initial time */ 156 struct ssp_rng* rng, 157 struct rwalk* rwalk, 158 const struct rwalk_context* ctx, 159 struct temperature* T); 160 161 /* Check the validity of the parametric coordinate onto a 2D primitive. If it 162 * is invalid, the function prints an error message and return RES_BAD_ARG. */ 163 extern LOCAL_SYM res_T 164 check_primitive_uv_2d 165 (struct sdis_device* dev, 166 const double u[]); 167 168 /* Check the validity of the parametric coordinates onto a 3D primitive. If 169 * they are invalid, the function prints an error message and return 170 * RES_BAD_ARG. */ 171 extern LOCAL_SYM res_T 172 check_primitive_uv_3d 173 (struct sdis_device* dev, 174 const double uv[]); 175 176 #endif /* SDIS_MISC_H */