atrstm_radcoefs_simd4.c (6244B)
1 /* Copyright (C) 2022, 2023 |Méso|Star> (contact@meso-star.com) 2 * Copyright (C) 2020, 2021 Centre National de la Recherche Scientifique 3 * 4 * This program is free software: you can redistribute it and/or modify 5 * it under the terms of the GNU General Public License as published by 6 * the Free Software Foundation, either version 3 of the License, or 7 * (at your option) any later version. 8 * 9 * This program is distributed in the hope that it will be useful, 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 * GNU General Public License for more details. 13 * 14 * You should have received a copy of the GNU General Public License 15 * along with this program. If not, see <http://www.gnu.org/licenses/>. */ 16 17 #include "atrstm_c.h" 18 #include "atrstm_log.h" 19 #include "atrstm_radcoefs.h" 20 #include "atrstm_radcoefs_simd4.h" 21 22 #include <astoria/atrtp.h> 23 #include <star/suvm.h> 24 25 #include <rsys/cstr.h> 26 27 /******************************************************************************* 28 * Local functions 29 ******************************************************************************/ 30 res_T 31 fetch_radcoefs_simd4 32 (const struct atrstm* atrstm, 33 const struct atrstm_fetch_radcoefs_args* args, 34 atrstm_radcoefs_T radcoefs) 35 { 36 struct radcoefs_simd4 prim_radcoefs; 37 v4f_T bcoords; 38 res_T res = RES_OK; 39 40 if(!atrstm 41 || !check_fetch_radcoefs_args(atrstm, args, FUNC_NAME) 42 || !radcoefs) { 43 res = RES_BAD_ARG; 44 goto error; 45 } 46 memset(radcoefs, 0, sizeof(double[ATRSTM_RADCOEFS_COUNT__])); 47 48 /* Compute the radiative properties of the primitive nodes */ 49 res = primitive_compute_radcoefs_simd4(atrstm, &atrstm->refract_id, 50 &args->prim, args->radcoefs_mask, &prim_radcoefs); 51 if(res != RES_OK) { 52 log_err(atrstm, 53 "Error computing the radiative properties for the primitive %lu -- %s.\n", 54 (unsigned long)args->prim.iprim, 55 res_to_cstr(res)); 56 goto error; 57 } 58 59 bcoords = v4f_set 60 ((float)args->bcoords[0], 61 (float)args->bcoords[1], 62 (float)args->bcoords[2], 63 (float)args->bcoords[3]); 64 65 /* Linearly interpolate the node radiative properties */ 66 if(args->radcoefs_mask & ATRSTM_RADCOEF_FLAG_Ka) { 67 const float prim_ka_min = v4f_x(v4f_reduce_min(prim_radcoefs.ka)); 68 const float prim_ka_max = v4f_x(v4f_reduce_max(prim_radcoefs.ka)); 69 radcoefs[ATRSTM_RADCOEF_Ka] = v4f_x(v4f_dot(prim_radcoefs.ka, bcoords)); 70 radcoefs[ATRSTM_RADCOEF_Ka] = /* Handle numerical uncertainty */ 71 CLAMP(radcoefs[ATRSTM_RADCOEF_Ka], prim_ka_min, prim_ka_max); 72 ASSERT(radcoefs[ATRSTM_RADCOEF_Ka] >= args->k_min[ATRSTM_RADCOEF_Ka]); 73 ASSERT(radcoefs[ATRSTM_RADCOEF_Ka] <= args->k_max[ATRSTM_RADCOEF_Ka]); 74 } 75 if(args->radcoefs_mask & ATRSTM_RADCOEF_FLAG_Ks) { 76 const float prim_ks_min = v4f_x(v4f_reduce_min(prim_radcoefs.ks)); 77 const float prim_ks_max = v4f_x(v4f_reduce_max(prim_radcoefs.ks)); 78 radcoefs[ATRSTM_RADCOEF_Ks] = v4f_x(v4f_dot(prim_radcoefs.ks, bcoords)); 79 radcoefs[ATRSTM_RADCOEF_Ks] = /* Handle numerical uncertainty */ 80 CLAMP(radcoefs[ATRSTM_RADCOEF_Ks], prim_ks_min, prim_ks_max); 81 ASSERT(radcoefs[ATRSTM_RADCOEF_Ks] >= args->k_min[ATRSTM_RADCOEF_Ks]); 82 ASSERT(radcoefs[ATRSTM_RADCOEF_Ks] <= args->k_max[ATRSTM_RADCOEF_Ks]); 83 } 84 if(args->radcoefs_mask & ATRSTM_RADCOEF_FLAG_Kext) { 85 const float prim_kext_min = v4f_x(v4f_reduce_min(prim_radcoefs.kext)); 86 const float prim_kext_max = v4f_x(v4f_reduce_max(prim_radcoefs.kext)); 87 radcoefs[ATRSTM_RADCOEF_Kext] = v4f_x(v4f_dot(prim_radcoefs.kext, bcoords)); 88 radcoefs[ATRSTM_RADCOEF_Kext] = /* Handle numerical uncertainty */ 89 CLAMP(radcoefs[ATRSTM_RADCOEF_Kext], prim_kext_min, prim_kext_max); 90 ASSERT(radcoefs[ATRSTM_RADCOEF_Kext] >= args->k_min[ATRSTM_RADCOEF_Kext]); 91 ASSERT(radcoefs[ATRSTM_RADCOEF_Kext] <= args->k_max[ATRSTM_RADCOEF_Kext]); 92 } 93 94 exit: 95 return res; 96 error: 97 goto exit; 98 } 99 100 res_T 101 primitive_compute_radcoefs_simd4 102 (const struct atrstm* atrstm, 103 const struct atrri_refractive_index* refract_id, 104 const struct suvm_primitive* prim, 105 const int radcoefs_mask, /* Combination of atrstm_radcoef_flag */ 106 struct radcoefs_simd4* radcoefs) 107 { 108 struct radcoefs_compute_simd4_args args = RADCOEFS_COMPUTE_SIMD4_ARGS_NULL; 109 struct atrtp_desc desc = ATRTP_DESC_NULL; 110 const double* node[4]; 111 res_T res = RES_OK; 112 ASSERT(atrstm && prim && prim->nvertices == 4 && refract_id && radcoefs); 113 114 res = atrtp_get_desc(atrstm->atrtp, &desc); 115 if(res != RES_OK) goto error; 116 117 /* Setup the constant input arguments of the optical properties computation 118 * routine */ 119 args.lambda = v4f_set1((float)refract_id->wavelength); 120 args.n = v4f_set1((float)refract_id->n); 121 args.kappa = v4f_set1((float)refract_id->kappa); 122 args.fractal_prefactor = v4f_set1((float)atrstm->fractal_prefactor); 123 args.fractal_dimension = v4f_set1((float)atrstm->fractal_dimension); 124 args.radcoefs_mask = radcoefs_mask; 125 126 /* Fetch the thermodynamic properties of the 4 primitive nodes */ 127 node[0] = atrtp_desc_get_node_properties(&desc, prim->indices[0]); 128 node[1] = atrtp_desc_get_node_properties(&desc, prim->indices[1]); 129 node[2] = atrtp_desc_get_node_properties(&desc, prim->indices[2]); 130 node[3] = atrtp_desc_get_node_properties(&desc, prim->indices[3]); 131 132 /* Scatter Soot properties */ 133 args.soot_volumic_fraction = v4f_set 134 ((float)node[0][ATRTP_SOOT_VOLFRAC], 135 (float)node[1][ATRTP_SOOT_VOLFRAC], 136 (float)node[2][ATRTP_SOOT_VOLFRAC], 137 (float)node[3][ATRTP_SOOT_VOLFRAC]); 138 args.soot_primary_particles_count = v4f_set 139 ((float)node[0][ATRTP_SOOT_PRIMARY_PARTICLES_COUNT], 140 (float)node[1][ATRTP_SOOT_PRIMARY_PARTICLES_COUNT], 141 (float)node[2][ATRTP_SOOT_PRIMARY_PARTICLES_COUNT], 142 (float)node[3][ATRTP_SOOT_PRIMARY_PARTICLES_COUNT]); 143 args.soot_primary_particles_diameter = v4f_set 144 ((float)node[0][ATRTP_SOOT_PRIMARY_PARTICLES_DIAMETER], 145 (float)node[1][ATRTP_SOOT_PRIMARY_PARTICLES_DIAMETER], 146 (float)node[2][ATRTP_SOOT_PRIMARY_PARTICLES_DIAMETER], 147 (float)node[3][ATRTP_SOOT_PRIMARY_PARTICLES_DIAMETER]); 148 149 /* Compute the per primitive node optical properties */ 150 radcoefs_compute_simd4(radcoefs, &args); 151 152 exit: 153 return res; 154 error: 155 goto exit; 156 }