test_ssol_solver4.c (7440B)
1 /* Copyright (C) 2018-2026 |Meso|Star> (contact@meso-star.com) 2 * Copyright (C) 2016, 2018 CNRS 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 "ssol.h" 18 #include "test_ssol_utils.h" 19 #include "test_ssol_materials.h" 20 21 #define PLANE_NAME SQUARE 22 #define HALF_X 0.1 23 #define HALF_Y 0.1 24 #include "test_ssol_rect_geometry.h" 25 26 #define POLYGON_NAME POLY 27 #define HALF_X 10 28 #define HALF_Y 10 29 #include "test_ssol_rect2D_geometry.h" 30 31 #include <rsys/double33.h> 32 33 #include <star/s3d.h> 34 #include <star/ssp.h> 35 36 static void 37 get_wlen(const size_t i, double* wlen, double* data, void* ctx) 38 { 39 double wavelengths[3] = { 1, 2, 3 }; 40 double intensities[3] = { 1, 0.8, 1 }; 41 CHK(i < 3); 42 (void)ctx; 43 *wlen = wavelengths[i]; 44 *data = intensities[i]; 45 } 46 47 int 48 main(int argc, char** argv) 49 { 50 struct mem_allocator allocator; 51 struct ssol_device* dev; 52 struct ssp_rng* rng; 53 struct ssol_scene* scene; 54 struct ssol_shape* square; 55 struct ssol_vertex_data attribs[1] = { SSOL_VERTEX_DATA_NULL__ }; 56 struct ssol_shape* quad_square; 57 struct ssol_carving carving = SSOL_CARVING_NULL; 58 struct ssol_quadric quadric = SSOL_QUADRIC_DEFAULT; 59 struct ssol_punched_surface punched = SSOL_PUNCHED_SURFACE_NULL; 60 struct ssol_material* m_mtl; 61 struct ssol_material* v_mtl; 62 struct ssol_mirror_shader shader = SSOL_MIRROR_SHADER_NULL; 63 struct ssol_object* m_object; 64 struct ssol_object* t_object; 65 struct ssol_instance* heliostat; 66 struct ssol_instance* target1; 67 struct ssol_instance* target2; 68 struct ssol_sun* sun; 69 struct ssol_spectrum* spectrum; 70 struct ssol_estimator* estimator; 71 struct ssol_mc_global mc_global; 72 struct ssol_mc_receiver mc_rcv; 73 double dir[3]; 74 double transform[12]; /* 3x4 column major matrix */ 75 size_t count; 76 double m1, std1, m2, std2; 77 78 (void) argc, (void) argv; 79 #define FOCAL 10 80 d3_splat(transform + 9, 0); 81 d33_rotation_pitch(transform, PI); /* flip faces: invert normal */ 82 transform[11] = FOCAL; /* +FOCAL offset along Z axis */ 83 84 mem_init_proxy_allocator(&allocator, &mem_default_allocator); 85 86 CHK(ssol_device_create 87 (NULL, &allocator, SSOL_NTHREADS_DEFAULT, 0, &dev) == RES_OK); 88 89 CHK(ssp_rng_create(&allocator, SSP_RNG_THREEFRY, &rng) == RES_OK); 90 CHK(ssol_spectrum_create(dev, &spectrum) == RES_OK); 91 CHK(ssol_spectrum_setup(spectrum, get_wlen, 3, NULL) == RES_OK); 92 CHK(ssol_sun_create_directional(dev, &sun) == RES_OK); 93 CHK(ssol_sun_set_direction(sun, d3(dir, 0, 0, -1)) == RES_OK); 94 CHK(ssol_sun_set_spectrum(sun, spectrum) == RES_OK); 95 CHK(ssol_sun_set_dni(sun, 1000) == RES_OK); 96 CHK(ssol_scene_create(dev, &scene) == RES_OK); 97 CHK(ssol_scene_attach_sun(scene, sun) == RES_OK); 98 99 /* Create scene content */ 100 101 CHK(ssol_shape_create_mesh(dev, &square) == RES_OK); 102 attribs[0].usage = SSOL_POSITION; 103 attribs[0].get = get_position; 104 CHK(ssol_mesh_setup(square, SQUARE_NTRIS__, get_ids, 105 SQUARE_NVERTS__, attribs, 1, (void*) &SQUARE_DESC__) == RES_OK); 106 107 CHK(ssol_shape_create_punched_surface(dev, &quad_square) == RES_OK); 108 carving.get = get_polygon_vertices; 109 carving.operation = SSOL_AND; 110 carving.nb_vertices = POLY_NVERTS__; 111 carving.context = &POLY_EDGES__; 112 quadric.type = SSOL_QUADRIC_PARABOL; 113 quadric.data.parabol.focal = FOCAL; 114 quadric.slices_count_hint = 100; 115 punched.nb_carvings = 1; 116 punched.quadric = &quadric; 117 punched.carvings = &carving; 118 CHK(ssol_punched_surface_setup(quad_square, &punched) == RES_OK); 119 120 CHK(ssol_material_create_mirror(dev, &m_mtl) == RES_OK); 121 shader.normal = get_shader_normal; 122 shader.reflectivity = get_shader_reflectivity; 123 shader.roughness = get_shader_roughness; 124 CHK(ssol_mirror_setup(m_mtl, &shader, SSOL_MICROFACET_BECKMANN) == RES_OK); 125 CHK(ssol_material_create_virtual(dev, &v_mtl) == RES_OK); 126 127 CHK(ssol_object_create(dev, &m_object) == RES_OK); 128 CHK(ssol_object_add_shaded_shape(m_object, quad_square, m_mtl, m_mtl) == RES_OK); 129 CHK(ssol_object_instantiate(m_object, &heliostat) == RES_OK); 130 CHK(ssol_scene_attach_instance(scene, heliostat) == RES_OK); 131 132 CHK(ssol_object_create(dev, &t_object) == RES_OK); 133 CHK(ssol_object_add_shaded_shape(t_object, square, v_mtl, v_mtl) == RES_OK); 134 CHK(ssol_object_instantiate(t_object, &target1) == RES_OK); 135 CHK(ssol_instance_set_transform(target1, transform) == RES_OK); 136 CHK(ssol_instance_set_receiver(target1, SSOL_FRONT, 0) == RES_OK); 137 CHK(ssol_instance_sample(target1, 0) == RES_OK); 138 CHK(ssol_scene_attach_instance(scene, target1) == RES_OK); 139 CHK(ssol_object_instantiate(t_object, &target2) == RES_OK); 140 transform[11] += 1.e-4; 141 CHK(ssol_instance_set_transform(target2, transform) == RES_OK); 142 CHK(ssol_instance_set_receiver(target2, SSOL_FRONT, 0) == RES_OK); 143 CHK(ssol_instance_sample(target2, 0) == RES_OK); 144 CHK(ssol_scene_attach_instance(scene, target2) == RES_OK); 145 146 #define N__ 100000 147 #define GET_MC_RCV ssol_estimator_get_mc_receiver 148 CHK(ssol_solve(scene, rng, N__, 0, NULL, &estimator) == RES_OK); 149 CHK(ssol_estimator_get_realisation_count(estimator, &count) == RES_OK); 150 CHK(count == N__); 151 #define COS cos(0) 152 #define DNI_cos (1000 * COS) 153 m1 = 400 * DNI_cos; 154 std1 = 0; 155 m2 = m1; 156 std2 = std1; 157 CHK(ssol_estimator_get_mc_global(estimator, &mc_global) == RES_OK); 158 print_global(&mc_global); 159 CHK(eq_eps(mc_global.shadowed.E, 0, 1e-4) == 1); 160 CHK(eq_eps(mc_global.missing.E, 400 * DNI_cos, 1e-2) == 1); /* virtual => 100 % missing */ 161 CHK(GET_MC_RCV(estimator, target1, SSOL_FRONT, &mc_rcv) == RES_OK); 162 printf("Ir(target1) = %g +/- %g\n", 163 mc_rcv.incoming_flux.E, mc_rcv.incoming_flux.SE); 164 CHK(eq_eps(mc_rcv.incoming_flux.E, m1, 1e-2) == 1); 165 CHK(eq_eps(mc_rcv.incoming_flux.SE, std1, 1e-2) == 1); 166 CHK(GET_MC_RCV(estimator, target2, SSOL_FRONT, &mc_rcv) == RES_OK); 167 printf("Ir(target2) = %g +/- %g\n", 168 mc_rcv.incoming_flux.E, mc_rcv.incoming_flux.SE); 169 CHK(eq_eps(mc_rcv.incoming_flux.E, m2, 1e-2) == 1); 170 CHK(eq_eps(mc_rcv.incoming_flux.SE, std2, 1e-2) == 1); 171 CHK(ssol_estimator_get_failed_count(estimator, &count) == RES_OK); 172 CHK(count == 0); 173 174 /* Free data */ 175 CHK(ssol_instance_ref_put(heliostat) == RES_OK); 176 CHK(ssol_instance_ref_put(target1) == RES_OK); 177 CHK(ssol_instance_ref_put(target2) == RES_OK); 178 CHK(ssol_object_ref_put(m_object) == RES_OK); 179 CHK(ssol_object_ref_put(t_object) == RES_OK); 180 CHK(ssol_shape_ref_put(square) == RES_OK); 181 CHK(ssol_shape_ref_put(quad_square) == RES_OK); 182 CHK(ssol_material_ref_put(m_mtl) == RES_OK); 183 CHK(ssol_material_ref_put(v_mtl) == RES_OK); 184 CHK(ssol_estimator_ref_put(estimator) == RES_OK); 185 CHK(ssol_device_ref_put(dev) == RES_OK); 186 CHK(ssol_scene_ref_put(scene) == RES_OK); 187 CHK(ssp_rng_ref_put(rng) == RES_OK); 188 CHK(ssol_spectrum_ref_put(spectrum) == RES_OK); 189 CHK(ssol_sun_ref_put(sun) == RES_OK); 190 191 check_memory_allocator(&allocator); 192 mem_shutdown_proxy_allocator(&allocator); 193 CHK(mem_allocated_size() == 0); 194 195 return 0; 196 } 197