test_sphor_MVREA_btdf_snell_dielectric.c (8139B)
1 /* Copyright (C) 2024-2026 Centre National de la Recherche Scientifique 2 * Copyright (C) 2024-2026 Clermont Auvergne INP 3 * Copyright (C) 2024-2026 INSA Lyon 4 * Copyright (C) 2024-2026 Institut Mines Télécom Albi-Carmaux 5 * Copyright (C) 2024-2026 Institut National Polytechnique de Toulouse 6 * Copyright (C) 2024-2026 |Méso|Star> (contact@meso-star.com) 7 * Copyright (C) 2024-2026 PhotonLyX (info@photonlyx.com) 8 * Copyright (C) 2024-2026 Université de Lorraine 9 * Copyright (C) 2024-2026 Université Paul Sabatier 10 * Copyright (C) 2024-2026 Université Toulouse - Jean Jaurès 11 * 12 * This program is free software: you can redistribute it and/or modify 13 * it under the terms of the GNU General Public License as published by 14 * the Free Software Foundation, either version 3 of the License, or 15 * (at your option) any later version. 16 * 17 * This program is distributed in the hope that it will be useful, 18 * but WITHOUT ANY WARRANTY; without even the implied warranty of 19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 20 * GNU General Public License for more details. 21 * 22 * You should have received a copy of the GNU General Public License 23 * along with this program. If not, see <http://www.gnu.org/licenses/>. */ 24 #define _POSIX_C_SOURCE 200112L 25 26 #include "sphor.h" 27 28 #include <rsys/cstr.h> 29 #include <rsys/logger.h> 30 #include <rsys/str.h> 31 #include <rsys/text_reader.h> 32 33 #include <stdio.h> 34 35 static void 36 write_emitting_surface() 37 { 38 FILE* fp = fopen("emitting_surface.stl", "w"); 39 CHK(fp != NULL); 40 41 fprintf(fp, 42 "solid emitting_surface\n" 43 " facet normal 0.5 0.8660254037844386 0\n" 44 " outer loop\n" 45 " vertex -1.4433756729740643 -1.5 -1\n" 46 " vertex -0.5773502691896257 -2 1\n" 47 " vertex -0.5773502691896257 -2 -1\n" 48 " endloop\n" 49 " endfacet\n" 50 " facet normal 0.5 0.8660254037844386 0\n" 51 " outer loop\n" 52 " vertex -0.5773502691896257 -2 1\n" 53 " vertex -1.4433756729740643 -1.5 -1\n" 54 " vertex -1.4433756729740643 -1.5 1\n" 55 " endloop\n" 56 " endfacet\n" 57 "endsolid emitting_surface\n"); 58 59 CHK(fclose(fp) == 0); 60 } 61 62 static void 63 write_btdf_surface() 64 { 65 FILE* fp = fopen("btdf_surface.stl", "w"); 66 CHK(fp != NULL); 67 68 fprintf(fp, 69 "solid btdf_surface\n" 70 " facet normal 1 0 0\n" 71 " outer loop\n" 72 " vertex 0 -1 -1\n" 73 " vertex 0 1 1\n" 74 " vertex 0 -1 1\n" 75 " endloop\n" 76 " endfacet\n" 77 " facet normal 1 0 0\n" 78 " outer loop\n" 79 " vertex 0 -1 -1\n" 80 " vertex 0 1 -1\n" 81 " vertex 0 1 1\n" 82 " endloop\n" 83 " endfacet\n" 84 "endsolid btdf_surface\n"); 85 86 CHK(fclose(fp) == 0); 87 } 88 89 static void 90 write_absorbing_surface() 91 { 92 FILE* fp = fopen("absorbing_surface.stl", "w"); 93 CHK(fp != NULL); 94 95 fprintf(fp, 96 "solid absorbing_surface\n" 97 "facet normal 0 0 0\n" 98 "outer loop\n" 99 "vertex 1.7320508075688772 0 -1\n" 100 "vertex 1.7320508075688772 0 1\n" 101 "vertex 0.8660254037844386 1.5 1\n" 102 "endloop\n" 103 "endfacet\n" 104 "facet normal 0 0 0\n" 105 "outer loop\n" 106 "vertex 0.8660254037844386 1.5 1\n" 107 "vertex 0.8660254037844386 1.5 -1\n" 108 "vertex 1.7320508075688772 0 -1\n" 109 "endloop\n" 110 "endfacet\n" 111 "endsolid absorbing_surface\n"); 112 113 CHK(fclose(fp) == 0); 114 } 115 116 static void 117 write_spectrum() 118 { 119 FILE* fp = fopen("emission_spectrum.dat", "w"); 120 CHK(fp != NULL); 121 122 fprintf(fp, "400 1\n"); 123 fprintf(fp, "401 1\n"); 124 125 CHK(fclose(fp) == 0); 126 } 127 128 static void 129 write_btdf() 130 { 131 FILE* fp = fopen("btdf.dat", "w"); 132 CHK(fp != NULL); 133 134 fprintf(fp, "400 1\n"); 135 fprintf(fp, "401 1\n"); 136 137 CHK(fclose(fp) == 0); 138 } 139 140 static void 141 write_bsdf_null() 142 { 143 FILE* fp = fopen("bsdf_null.dat", "w"); 144 CHK(fp != NULL); 145 146 fprintf(fp, "400 0\n"); 147 fprintf(fp, "401 0\n"); 148 149 CHK(fclose(fp) == 0); 150 } 151 152 static void 153 write_n_back() 154 { 155 FILE* fp = fopen("n_back.dat", "w"); 156 CHK(fp != NULL); 157 158 fprintf(fp, "400 1\n"); 159 fprintf(fp, "401 1\n"); 160 161 CHK(fclose(fp) == 0); 162 } 163 164 static void 165 write_n_front() 166 { 167 FILE* fp = fopen("n_front.dat", "w"); 168 CHK(fp != NULL); 169 170 fprintf(fp, "400 1.7320508075688772\n"); 171 fprintf(fp, "401 1.7320508075688772\n"); 172 173 CHK(fclose(fp) == 0); 174 } 175 176 static void 177 write_input_file(FILE* fp) 178 { 179 write_emitting_surface(); 180 write_btdf_surface(); 181 write_absorbing_surface(); 182 write_spectrum(); 183 write_btdf(); 184 write_bsdf_null(); 185 write_n_front(); 186 write_n_back(); 187 188 fprintf(fp, "surface: \"source\"\n"); 189 fprintf(fp, "\tgeometry: FRONT emitting_surface.stl\n"); 190 fprintf(fp, "\tsource:\n"); 191 fprintf(fp, "\tflux_density: 1.7320508075688772 umol/m^2/s"); 192 fprintf(fp, " emission_spectrum.dat nm nm^-1\n"); 193 fprintf(fp, "\t\tdirection: COLLIM NORMAL\n"); 194 fprintf(fp, "\n"); 195 196 fprintf(fp, "surface: \"transmitter\"\n"); 197 fprintf(fp, "\tgeometry: BACK btdf_surface.stl\n"); 198 fprintf(fp, "\tbtdf: SNELL_DIELECTRIC btdf.dat\n"); 199 fprintf(fp, "\n"); 200 201 fprintf(fp, "surface: \"absorber\"\n"); 202 fprintf(fp, "\tgeometry: FRONT absorbing_surface.stl\n"); 203 fprintf(fp, "\tbrdf: SPECULAR bsdf_null.dat\n"); 204 fprintf(fp, "\tsensor:\n"); 205 fprintf(fp, "\t\tresponse_function: 1\n"); 206 207 fprintf(fp, "volume: \"n_front\"\n"); 208 fprintf(fp, "\tgeometry: FRONT btdf_surface.stl\n"); 209 fprintf(fp, "\trefractive_index:\n"); 210 fprintf(fp, "\t\tn_real: n_front.dat\n"); 211 212 fprintf(fp, "volume: \"n_back\"\n"); 213 fprintf(fp, "\tgeometry: BACK btdf_surface.stl\n"); 214 fprintf(fp, "\trefractive_index:\n"); 215 fprintf(fp, "\t\tn_real: n_back.dat\n"); 216 217 CHK(fflush(fp) == 0); 218 } 219 220 int main(int argc, char** argv) 221 { 222 struct sphor* sphor = NULL; 223 struct sphor_create_args args = SPHOR_CREATE_ARGS_DEFAULT; 224 struct txtrdr* txtrdr = NULL; 225 struct str line; 226 char* token = NULL; 227 char* token_ptr = NULL; 228 char input_filename[] = "input"; 229 char output_filename[] = "output"; 230 double avg = 0; 231 double std_err = 0; 232 233 FILE* fp = NULL; 234 235 fp = fopen(input_filename, "w+"); 236 CHK(NULL != fp); 237 238 write_input_file(fp); 239 CHK(fclose(fp) == 0); 240 241 args.input_filename = input_filename; 242 args.output_filename = output_filename; 243 args.force = 1; 244 245 (void)argc; 246 (void)argv; 247 248 /* Test sphor_create with NULL logger and allocator */ 249 CHK(sphor_create(&args, &sphor) == RES_OK); 250 251 /* Run sphor with the config file */ 252 CHK(sphor_run(sphor) == RES_OK); 253 254 CHK(sphor_ref_put(sphor) == RES_OK); 255 256 fp = fopen(output_filename, "r"); 257 CHK(NULL != fp); 258 259 str_init(NULL, &line); 260 CHK(txtrdr_stream(NULL, fp, output_filename, '#', &txtrdr) == RES_OK); 261 262 /* Verify first level: total scene MVREA */ 263 CHK(txtrdr_read_line(txtrdr) == RES_OK); 264 CHK(str_set(&line, txtrdr_get_cline(txtrdr)) == RES_OK); 265 token = strtok_r(str_get(&line), ":", &token_ptr); 266 CHK(strcmp(token, "MVREA") == 0); 267 token = strtok_r(NULL, ":", &token_ptr); 268 CHK(cstr_to_double(token, &avg) == RES_OK); 269 CHK(cstr_to_double(token_ptr, &std_err) == RES_OK); 270 /* Compare to analytical solution */ 271 CHK(eq_eps(avg, 0, 2 * std_err)); 272 273 /* Verify first level: total scene losses */ 274 CHK(txtrdr_read_line(txtrdr) == RES_OK); 275 CHK(str_set(&line, txtrdr_get_cline(txtrdr)) == RES_OK); 276 token = strtok_r(str_get(&line), ":", &token_ptr); 277 CHK(strcmp(token, "LOSSES") == 0); 278 token = strtok_r(NULL, ":", &token_ptr); 279 CHK(cstr_to_double(token, &avg) == RES_OK); 280 CHK(cstr_to_double(token_ptr, &std_err) == RES_OK); 281 /* Compare to analytical solution */ 282 CHK(eq_eps(avg, 1, 2 * std_err)); 283 284 /* Verify second level: per surface losses */ 285 CHK(txtrdr_read_line(txtrdr) == RES_OK); 286 CHK(str_set(&line, txtrdr_get_cline(txtrdr)) == RES_OK); 287 token = strtok_r(str_get(&line), ":", &token_ptr); 288 CHK(strcmp(token, "LOSSES") == 0); 289 token = strtok_r(NULL, ":", &token_ptr); 290 CHK(strcmp(token, "absorber") == 0); 291 token = strtok_r(NULL, ":", &token_ptr); 292 CHK(cstr_to_double(token, &avg) == RES_OK); 293 CHK(cstr_to_double(token_ptr, &std_err) == RES_OK); 294 /* Compare to analytical solution */ 295 CHK(eq_eps(avg, 1, 2 * std_err)); 296 297 CHK(fclose(fp) == 0); 298 299 str_release(&line); 300 txtrdr_ref_put(txtrdr); 301 302 CHK(mem_allocated_size() == 0); 303 304 return 0; 305 }