sdis_estimator.c (8427B)
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 #include "sdis.h" 17 #include "sdis_device_c.h" 18 #include "sdis_estimator_c.h" 19 #include "sdis_log.h" 20 21 #include <star/ssp.h> 22 23 #include <rsys/cstr.h> 24 #include <rsys/mutex.h> 25 26 /******************************************************************************* 27 * Helper functions 28 ******************************************************************************/ 29 static void 30 estimator_release(ref_T* ref) 31 { 32 struct sdis_estimator* estimator = NULL; 33 struct sdis_device* dev = NULL; 34 ASSERT(ref); 35 estimator = CONTAINER_OF(ref, struct sdis_estimator, ref); 36 dev = estimator->dev; 37 darray_heat_path_release(&estimator->paths); 38 if(estimator->mutex) mutex_destroy(estimator->mutex); 39 if(estimator->rng) SSP(rng_ref_put(estimator->rng)); 40 MEM_RM(dev->allocator, estimator); 41 SDIS(device_ref_put(dev)); 42 } 43 44 /******************************************************************************* 45 * Exported functions 46 ******************************************************************************/ 47 res_T 48 sdis_estimator_ref_get(struct sdis_estimator* estimator) 49 { 50 if(!estimator) return RES_BAD_ARG; 51 ref_get(&estimator->ref); 52 return RES_OK; 53 } 54 55 res_T 56 sdis_estimator_ref_put(struct sdis_estimator* estimator) 57 { 58 if(!estimator) return RES_BAD_ARG; 59 ref_put(&estimator->ref, estimator_release); 60 return RES_OK; 61 } 62 63 res_T 64 sdis_estimator_get_type 65 (const struct sdis_estimator* estimator, enum sdis_estimator_type* type) 66 { 67 if(!estimator || !type) return RES_BAD_ARG; 68 *type = estimator->type; 69 return RES_OK; 70 } 71 72 res_T 73 sdis_estimator_get_realisation_count 74 (const struct sdis_estimator* estimator, size_t* nrealisations) 75 { 76 if(!estimator || !nrealisations) return RES_BAD_ARG; 77 *nrealisations = estimator->nrealisations; 78 return RES_OK; 79 } 80 81 res_T 82 sdis_estimator_get_failure_count 83 (const struct sdis_estimator* estimator, size_t* nfailures) 84 { 85 if(!estimator || !nfailures) return RES_BAD_ARG; 86 *nfailures = estimator->nfailures; 87 return RES_OK; 88 } 89 90 #define SETUP_MC(Mc, Acc) { \ 91 (Mc)->E = (Acc)->sum / (double)(Acc)->count; \ 92 (Mc)->V = (Acc)->sum2 / (double)(Acc)->count - (Mc)->E*(Mc)->E; \ 93 (Mc)->V = MMAX((Mc)->V, 0); \ 94 (Mc)->SE = sqrt((Mc)->V / (double)(Acc)->count); \ 95 } (void)0 96 97 res_T 98 sdis_estimator_get_temperature 99 (const struct sdis_estimator* estimator, struct sdis_mc* mc) 100 { 101 if(!estimator || !mc 102 || ( estimator->type != SDIS_ESTIMATOR_TEMPERATURE 103 && estimator->type != SDIS_ESTIMATOR_FLUX)) 104 return RES_BAD_ARG; 105 SETUP_MC(mc, &estimator->temperature); 106 return RES_OK; 107 } 108 109 res_T 110 sdis_estimator_get_realisation_time 111 (const struct sdis_estimator* estimator, struct sdis_mc* mc) 112 { 113 if(!estimator || !mc) return RES_BAD_ARG; 114 SETUP_MC(mc, &estimator->realisation_time); 115 return RES_OK; 116 } 117 118 res_T 119 sdis_estimator_get_convective_flux 120 (const struct sdis_estimator* estimator, struct sdis_mc* flux) 121 { 122 if(!estimator || !flux || estimator->type != SDIS_ESTIMATOR_FLUX) 123 return RES_BAD_ARG; 124 SETUP_MC(flux, &estimator->fluxes[FLUX_CONVECTIVE]); 125 return RES_OK; 126 } 127 128 res_T 129 sdis_estimator_get_radiative_flux 130 (const struct sdis_estimator* estimator, struct sdis_mc* flux) 131 { 132 if(!estimator || !flux || estimator->type != SDIS_ESTIMATOR_FLUX) 133 return RES_BAD_ARG; 134 SETUP_MC(flux, &estimator->fluxes[FLUX_RADIATIVE]); 135 return RES_OK; 136 } 137 138 res_T 139 sdis_estimator_get_imposed_flux 140 (const struct sdis_estimator* estimator, struct sdis_mc* flux) 141 { 142 if(!estimator || !flux || estimator->type != SDIS_ESTIMATOR_FLUX) 143 return RES_BAD_ARG; 144 SETUP_MC(flux, &estimator->fluxes[FLUX_IMPOSED]); 145 return RES_OK; 146 } 147 148 res_T 149 sdis_estimator_get_total_flux 150 (const struct sdis_estimator* estimator, struct sdis_mc* flux) 151 { 152 if(!estimator || !flux || estimator->type != SDIS_ESTIMATOR_FLUX) 153 return RES_BAD_ARG; 154 SETUP_MC(flux, &estimator->fluxes[FLUX_TOTAL]); 155 return RES_OK; 156 } 157 158 res_T 159 sdis_estimator_get_power 160 (const struct sdis_estimator* estimator, struct sdis_mc* power) 161 { 162 if(!estimator || !power || estimator->type != SDIS_ESTIMATOR_POWER) 163 return RES_BAD_ARG; 164 SETUP_MC(power, &estimator->power.power); 165 power->E *= estimator->power.spread; 166 return RES_OK; 167 } 168 169 #undef SETUP_MC 170 171 res_T 172 sdis_estimator_get_paths_count 173 (const struct sdis_estimator* estimator, size_t* npaths) 174 { 175 if(!estimator || !npaths) return RES_BAD_ARG; 176 *npaths = darray_heat_path_size_get(&estimator->paths); 177 return RES_OK; 178 } 179 180 SDIS_API res_T 181 sdis_estimator_get_path 182 (const struct sdis_estimator* estimator, 183 const size_t ipath, 184 const struct sdis_heat_path** path) 185 { 186 if(!estimator || !path 187 || ipath >= darray_heat_path_size_get(&estimator->paths)) 188 return RES_BAD_ARG; 189 *path = darray_heat_path_cdata_get(&estimator->paths) + ipath; 190 return RES_OK; 191 } 192 193 res_T 194 sdis_estimator_for_each_path 195 (const struct sdis_estimator* estimator, 196 sdis_process_heat_path_T func, 197 void* context) 198 { 199 const struct sdis_heat_path* paths = NULL; 200 size_t i, n; 201 res_T res = RES_OK; 202 203 if(!estimator || !func) { 204 res = RES_BAD_ARG; 205 goto error; 206 } 207 208 SDIS(estimator_get_paths_count(estimator, &n)); 209 paths = darray_heat_path_cdata_get(&estimator->paths); 210 FOR_EACH(i, 0, n) { 211 res = func(paths+i, context); 212 if(res != RES_OK) goto error; 213 } 214 215 exit: 216 return res; 217 error: 218 goto exit; 219 } 220 221 res_T 222 sdis_estimator_get_rng_state 223 (const struct sdis_estimator* estimator, 224 struct ssp_rng** rng_state) 225 { 226 if(!estimator || !rng_state) return RES_BAD_ARG; 227 *rng_state = estimator->rng; 228 return RES_OK; 229 } 230 231 /******************************************************************************* 232 * Local functions 233 ******************************************************************************/ 234 res_T 235 estimator_create 236 (struct sdis_device* dev, 237 const enum sdis_estimator_type type, 238 struct sdis_estimator** out_estimator) 239 { 240 struct sdis_estimator* estimator = NULL; 241 res_T res = RES_OK; 242 243 if(!dev 244 || (unsigned)type >= SDIS_ESTIMATOR_TYPES_COUNT__ 245 || !out_estimator) { 246 res = RES_BAD_ARG; 247 goto error; 248 } 249 250 estimator = MEM_CALLOC(dev->allocator, 1, sizeof(struct sdis_estimator)); 251 if(!estimator) { 252 res = RES_MEM_ERR; 253 goto error; 254 } 255 ref_init(&estimator->ref); 256 SDIS(device_ref_get(dev)); 257 estimator->nrealisations = 0; 258 estimator->nfailures = 0; 259 estimator->dev = dev; 260 estimator->type = type; 261 darray_heat_path_init(dev->allocator, &estimator->paths); 262 263 estimator->mutex = mutex_create(); 264 if(!estimator->mutex) { 265 res = RES_MEM_ERR; 266 goto error; 267 } 268 269 exit: 270 if(out_estimator) *out_estimator = estimator; 271 return res; 272 error: 273 if(estimator) { 274 SDIS(estimator_ref_put(estimator)); 275 estimator = NULL; 276 } 277 goto exit; 278 } 279 280 res_T 281 estimator_add_and_release_heat_path 282 (struct sdis_estimator* estimator, struct sdis_heat_path* path) 283 { 284 struct sdis_heat_path* dst = NULL; 285 size_t i; 286 res_T res = RES_OK; 287 ASSERT(estimator && path); 288 289 mutex_lock(estimator->mutex); 290 291 i = darray_heat_path_size_get(&estimator->paths); 292 293 res = darray_heat_path_resize(&estimator->paths, i+1); 294 if(res != RES_OK) goto error; 295 296 dst = darray_heat_path_data_get(&estimator->paths) + i; 297 res = heat_path_copy_and_release(dst, path); 298 if(res != RES_OK) goto error; 299 300 exit: 301 mutex_unlock(estimator->mutex); 302 return res; 303 error: 304 goto exit; 305 } 306 307 res_T 308 estimator_save_rng_state 309 (struct sdis_estimator* estimator, 310 const struct ssp_rng_proxy* proxy) 311 { 312 ASSERT(estimator && proxy); 313 /* Release the previous RNG state if any */ 314 if(estimator->rng) { 315 SSP(rng_ref_put(estimator->rng)); 316 estimator->rng = NULL; 317 } 318 return create_rng_from_rng_proxy(estimator->dev, proxy, &estimator->rng); 319 } 320