stardis-solver

Solve coupled heat transfers
git clone git://git.meso-star.fr/stardis-solver.git
Log | Files | Refs | README | LICENSE

sdis_heat_path_conductive_custom_Xd.h (6363B)


      1 /* Copyright (C) 2016-2025 |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 "sdis.h"
     17 #include "sdis_log.h"
     18 #include "sdis_medium_c.h"
     19 #include "sdis_scene_c.h"
     20 
     21 #include <rsys/cstr.h>
     22 
     23 #include "sdis_Xd_begin.h"
     24 
     25 /*******************************************************************************
     26  * Helper function
     27  ******************************************************************************/
     28 static res_T
     29 XD(check_sampled_path)
     30   (struct sdis_scene* scn,
     31    const struct rwalk* rwalk,
     32    const struct sdis_path* path)
     33 {
     34   int null_prim = 0;
     35   res_T res = RES_OK;
     36   ASSERT(scn && path);
     37 
     38   null_prim = SXD_PRIMITIVE_EQ(&path->XD(prim), &SXD_PRIMITIVE_NULL);
     39 
     40   /* Check end of path */
     41   if(!path->at_limit && null_prim) {
     42     log_err(scn->dev,
     43       "%s: the sampled path should have reached a limit condition or a boundary"
     44       " -- pos=("FORMAT_VECX")\n",
     45       FUNC_NAME, SPLITX(path->vtx.P));
     46     res = RES_BAD_ARG;
     47     goto error;
     48   }
     49 
     50   /* Check path time */
     51   if(path->vtx.time > rwalk->vtx.time) {
     52     log_err(scn->dev,
     53       "%s: the sampled trajectory cannot be in the future. "
     54       "It can only go back in time -- starting time=%g s; current time=%g s\n",
     55       FUNC_NAME, rwalk->vtx.time, path->vtx.time);
     56     res = RES_BAD_ARG;
     57     goto error;
     58   }
     59 
     60   if(!null_prim) {
     61     struct sXd(primitive) prim;
     62     const unsigned iprim = path->XD(prim).prim_id;
     63 
     64     /* Check intersected primitive */
     65     res = sXd(scene_view_get_primitive)(scn->sXd(view), iprim, &prim);
     66     if(res != RES_OK || !SXD_PRIMITIVE_EQ(&path->XD(prim), &prim)) {
     67       log_err(scn->dev,
     68         "%s: invalid intersected primitive on sampled path -- %s\n",
     69         FUNC_NAME, res_to_cstr(res));
     70       goto error;
     71     }
     72   }
     73 
     74 exit:
     75   return res;
     76 error:
     77   goto exit;
     78 }
     79 
     80 static int
     81 XD(keep_only_one_primitive)
     82   (const struct sXd(hit)* hit,
     83    const float org[DIM],
     84    const float dir[DIM],
     85    const float range[2],
     86    void* query_data,
     87    void* filter_data)
     88 {
     89   const struct sXd(primitive)* prim = query_data;
     90   (void)org, (void)dir, (void)range, (void)filter_data;
     91   return !SXD_PRIMITIVE_EQ(prim, &hit->prim);
     92 }
     93 
     94 static res_T
     95 XD(get_path_hit)
     96   (struct sdis_scene* scn,
     97    struct sdis_path* path,
     98    const struct sdis_medium* mdm,
     99    struct sXd(hit)* hit)
    100 {
    101   struct hit_filter_data filter_data = HIT_FILTER_DATA_NULL;
    102   float query_radius = 0;
    103   float query_pos[DIM] = {0};
    104   double delta = 0;
    105   res_T res = RES_OK;
    106   ASSERT(scn && path && hit);
    107 
    108   filter_data.XD(custom_filter) = XD(keep_only_one_primitive);
    109   filter_data.custom_filter_data = &path->XD(prim);
    110 
    111   /* Search for the hit corresponding to the path position on a primitive. Search
    112    * at a maximum distance from the delta of the medium, as this hit should be
    113    * very close to the submitted position, since it should represent the same
    114    * point. */
    115   delta = solid_get_delta(mdm, &path->vtx);
    116   fX_set_dX(query_pos, path->vtx.P);
    117   query_radius = (float)delta;
    118   SXD(scene_view_closest_point(scn->sXd(view), query_pos, query_radius,
    119       &filter_data, hit));
    120   ASSERT(SXD_PRIMITIVE_EQ(&hit->prim, &path->XD(prim)));
    121 
    122   if(SXD_HIT_NONE(hit)) {
    123     log_warn(scn->dev,
    124       "%s: the position returned by custom sampling of the conductive path "
    125       "is too far from the primitive it should be on -- "
    126       "query position=("FORMAT_VECX"); search distance=%g\n",
    127       FUNC_NAME, SPLITX(path->vtx.P), delta);
    128     res = RES_BAD_OP;
    129     goto error;
    130   }
    131 
    132 exit:
    133   return res;
    134 error:
    135   goto exit;
    136 }
    137 
    138 /*******************************************************************************
    139  * Local function
    140  ******************************************************************************/
    141 res_T
    142 XD(conductive_path_custom)
    143   (struct sdis_scene* scn,
    144    const unsigned enc_id,
    145    const struct sdis_medium* mdm,
    146    struct rwalk* rwalk,
    147    struct ssp_rng* rng,
    148    struct temperature* T)
    149 {
    150   struct sdis_path path = SDIS_PATH_NULL;
    151   res_T res = RES_OK;
    152 
    153   /* Check pre-conditions */
    154   ASSERT(scn && rwalk && rng && T);
    155   ASSERT(sdis_medium_get_type(mdm) == SDIS_SOLID);
    156   ASSERT(mdm->shader.solid.sample_path);
    157 
    158   /* Sample a conductive path */
    159   path.vtx = rwalk->vtx;
    160   res = mdm->shader.solid.sample_path(scn, rng, &path, mdm->data);
    161   if(res != RES_OK) {
    162     log_err(scn->dev,
    163       "%s: error in customized sampling of a conductive path "
    164       "from pos=("FORMAT_VECX") -- %s\n",
    165       FUNC_NAME, SPLITX(rwalk->vtx.P), res_to_cstr(res));
    166     goto error;
    167   }
    168 
    169   res = XD(check_sampled_path)(scn, rwalk, &path);
    170   if(res!= RES_OK) goto error;
    171 
    172   /* Update random walk position and time from sampled path */
    173   rwalk->elapsed_time += rwalk->vtx.time - path.vtx.time;
    174   rwalk->vtx = path.vtx;
    175 
    176   /* Calculate path intersection with geometry if it hasn't already reached a
    177    * boundary condition */
    178   if(!path.at_limit) {
    179     res = XD(get_path_hit)(scn, &path, mdm, &rwalk->XD(hit));
    180     if(res != RES_OK) goto error;
    181   }
    182 
    183 
    184   /* The path reached a boundary */
    185   if(!SXD_HIT_NONE(&rwalk->XD(hit))) {
    186     unsigned enc_ids[2] = {ENCLOSURE_ID_NULL, ENCLOSURE_ID_NULL};
    187 
    188     rwalk->enc_id = ENCLOSURE_ID_NULL; /* Not in an enclosure */
    189 
    190       /* Define which side of the interface the path is on */
    191     scene_get_enclosure_ids(scn, rwalk->XD(hit).prim.prim_id, enc_ids);
    192          if(enc_id == enc_ids[SDIS_FRONT]) rwalk->hit_side = SDIS_FRONT;
    193     else if(enc_id == enc_ids[SDIS_BACK])  rwalk->hit_side = SDIS_BACK;
    194     else FATAL("Unreachable code.\n");
    195   }
    196 
    197   /* Update Monte Carlo weight */
    198   T->value += path.weight;
    199   T->done = path.at_limit;
    200 
    201   /* The path either reaches a boundary condition and will be stopped, or is
    202    * on a boundary and a boundary path must be sampled */
    203   T->func = XD(boundary_path);
    204 
    205 exit:
    206   return res;
    207 error:
    208   goto exit;
    209 }
    210 
    211 #include "sdis_Xd_end.h"