s4vs.c (6159B)
1 /* Copyright (C) 2015-2018, 2021, 2024 |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 "s4vs_args.h" 17 #include "s4vs_realization.h" 18 19 #include <star/s3d.h> 20 #include <star/s3daw.h> 21 #include <star/smc.h> 22 23 #include <rsys/cstr.h> 24 #include <rsys/float3.h> 25 #include <rsys/mem_allocator.h> 26 #include <rsys/clock_time.h> 27 28 /******************************************************************************* 29 * Helper functions 30 ******************************************************************************/ 31 static res_T 32 compute_4v_s 33 (struct s3d_scene* scene, 34 const size_t max_realisations, 35 const double ks) 36 { 37 /* Star-Monte Carlo */ 38 struct smc_device_create_args args = SMC_DEVICE_CREATE_ARGS_DEFAULT; 39 struct smc_estimator_status estimator_status = SMC_ESTIMATOR_STATUS_NULL; 40 struct smc_integrator integrator = SMC_INTEGRATOR_NULL; 41 struct smc_device* smc = NULL; 42 struct smc_estimator* estimator = NULL; 43 44 /* Miscellaneous */ 45 char dump[64]; 46 struct s4vs_context ctx; 47 struct s3d_scene_view* view = NULL; 48 struct time t0, t1; 49 float S, V, reference; 50 res_T res = RES_OK; 51 ASSERT(scene && max_realisations > 0 && ks >= 0); 52 53 S3D(scene_view_create(scene, S3D_SAMPLE|S3D_TRACE, &view)); 54 55 /* Compute the expected result using a mesh-based method */ 56 S3D(scene_view_compute_area(view, &S)); 57 S3D(scene_view_compute_volume(view, &V)); 58 if(eq_epsf(S, 0, 1.e-6f) || S < 0) { 59 fprintf(stderr, "No surface to sample. Is the scene empty?\n"); 60 res = RES_BAD_ARG; 61 goto error; 62 } 63 if(eq_epsf(V, 0, 1.e-6f) || V < 0) { 64 fprintf(stderr, 65 "Invalid volume \"%.2f\". The scene might not match the prerequisites:\n" 66 "it must be closed and its normals must point *into* the volume.\n", V); 67 res = RES_BAD_ARG; 68 goto error; 69 } 70 reference = 4*V/S; 71 72 /* Initialize context for MC computation */ 73 ctx.view = view; 74 ctx.ks = ks; 75 ctx.g = PI/4.0; 76 77 /* Setup Star-MC */ 78 args.verbose = 1; 79 SMC(device_create(&args, &smc)); 80 integrator.integrand = &s4vs_realization; /* Realization function */ 81 integrator.type = &smc_double; /* Type of the Monte Carlo weight */ 82 integrator.max_realisations = max_realisations; /* Realization count */ 83 integrator.max_failures = max_realisations / 1000; 84 85 /* Solve */ 86 time_current(&t0); 87 SMC(solve(smc, &integrator, &ctx, &estimator)); 88 time_sub(&t0, time_current(&t1), &t0); 89 time_dump(&t0, TIME_ALL, NULL, dump, sizeof(dump)); 90 printf("Computation time: %s\n", dump); 91 92 /* Print the simulation results */ 93 SMC(estimator_get_status(estimator, &estimator_status)); 94 95 if(estimator_status.NF > integrator.max_failures) { 96 fprintf(stderr, 97 "Too many failures (%lu). The scene might not match the prerequisites:\n" 98 "it must be closed and its normals must point *into* the volume.\n", 99 (unsigned long)estimator_status.NF); 100 goto error; 101 } 102 printf("4V/S = %g ~ %g +/- %g\n#failures = %lu/%lu\n", 103 reference, 104 SMC_DOUBLE(estimator_status.E), 105 SMC_DOUBLE(estimator_status.SE), 106 (unsigned long)estimator_status.NF, 107 (unsigned long)max_realisations); 108 109 exit: 110 /* Clean-up data */ 111 if(view) S3D(scene_view_ref_put(view)); 112 if(smc) SMC(device_ref_put(smc)); 113 if(estimator) SMC(estimator_ref_put(estimator)); 114 return res; 115 116 error: 117 goto exit; 118 } 119 120 /* Create a S3D scene from an obj in a scene */ 121 static res_T 122 import_obj(const char* filename, struct s3d_scene** out_scene) 123 { 124 /* Star-3D */ 125 struct s3d_device* s3d = NULL; 126 struct s3d_scene* scene = NULL; 127 128 /* Star-3DAW */ 129 struct s3daw* s3daw = NULL; 130 size_t ishape, nshapes; 131 132 /* Miscellaneous */ 133 char dump[64]; 134 struct time t0, t1; 135 res_T res = RES_OK; 136 137 ASSERT(out_scene); /* Pre-condition */ 138 139 S3D(device_create(NULL, NULL, 0/*verbose?*/, &s3d)); 140 S3DAW(create(NULL, NULL, NULL, NULL, s3d, 1/*verbose?*/, &s3daw)); 141 142 time_current(&t0); 143 if(filename) { 144 res = s3daw_load(s3daw, filename); 145 } else { 146 res = s3daw_load_stream(s3daw, stdin); 147 } 148 if(res != RES_OK) { 149 fprintf(stderr, "Error loading obj -- %s\n", res_to_cstr(res)); 150 goto error; 151 } 152 time_current(&t1); 153 time_sub(&t0, &t1, &t0); 154 time_dump(&t0, TIME_ALL, NULL, dump, sizeof(dump)); 155 printf("Obj loaded in %s\n", dump); 156 157 S3DAW(get_shapes_count(s3daw, &nshapes)); 158 S3D(scene_create(s3d, &scene)); 159 160 FOR_EACH(ishape, 0, nshapes) { 161 struct s3d_shape* shape = NULL; 162 S3DAW(get_shape(s3daw, ishape, &shape)); 163 S3D(mesh_set_hit_filter_function(shape, s4vs_discard_self_hit, NULL)); 164 S3D(scene_attach_shape(scene, shape)); 165 } 166 167 exit: 168 /* Release memory */ 169 if(s3daw) S3DAW(ref_put(s3daw)); 170 if(s3d) S3D(device_ref_put(s3d)); 171 *out_scene = scene; 172 return res; 173 error: 174 if(scene) { 175 S3D(scene_ref_put(scene)); 176 scene = NULL; 177 } 178 goto exit; 179 } 180 181 /******************************************************************************* 182 * The program 183 ******************************************************************************/ 184 int 185 main(int argc, char* argv[]) 186 { 187 struct s4vs_args args = S4VS_ARGS_DEFAULT; 188 struct s3d_scene* scn = NULL; 189 res_T res = RES_OK; 190 int err = 0; 191 192 res = s4vs_args_init(&args, argc, argv); 193 if(res != RES_OK) goto error; 194 res = import_obj(args.filename, &scn); 195 if(res != RES_OK) goto error; 196 res = compute_4v_s(scn, args.nrealisations, args.ks); 197 if(res != RES_OK) goto error; 198 199 exit: 200 if(scn) S3D(scene_ref_put(scn)); 201 if(mem_allocated_size() != 0) { 202 fprintf(stderr, "Memory leaks: %lu Bytes\n", 203 (unsigned long)mem_allocated_size()); 204 err = 1; 205 } 206 return err; 207 error: 208 err = 1; 209 goto exit; 210 }