star-4v_s

An invariant property of diffuse random walks
git clone git://git.meso-star.fr/star-4v_s.git
Log | Files | Refs | README | LICENSE

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 }