schiff

Estimate the radiative properties of soft particless
git clone git://git.meso-star.com/schiff.git
Log | Files | Refs | README | LICENSE

schiff_optical_properties.c (6121B)


      1 /* Copyright (C) 2015-2016 CNRS
      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 "schiff_optical_properties.h"
     17 #include "schiff_streamline.h"
     18 
     19 #include <rsys/algorithm.h>
     20 #include <rsys/cstr.h>
     21 #include <rsys/stretchy_array.h>
     22 
     23 #include <star/sschiff.h>
     24 
     25 /*******************************************************************************
     26  * Helper functions
     27  ******************************************************************************/
     28 static res_T
     29 parse_optical_properties
     30   (struct schiff_optical_properties* out_props,
     31    const char* filename,
     32    const size_t iline,
     33    const char* str)
     34 {
     35   char buf[128];
     36   char* tk;
     37   int i = 0;
     38   double props[4];
     39   res_T res = RES_OK;
     40   ASSERT(filename && str && out_props);
     41 
     42   if(strlen(str) >= sizeof(buf) - 1/*NULL char*/) {
     43     fprintf(stderr,
     44       "%s:%lu: not enough memory: cannot parse the properties `%s'.\n",
     45       filename, (unsigned long)iline, str);
     46     return RES_MEM_ERR;
     47   }
     48 
     49   strncpy(buf, str, sizeof(buf));
     50   for(i=0, tk=strtok(buf, " \t"); tk && i < 4; ++i, tk=strtok(NULL, " \t")) {
     51     res = cstr_to_double(tk, props + i);
     52     if(res != RES_OK) {
     53       fprintf(stderr,
     54         "%s:%lu: cannot read the optical property `%s'.\n",
     55         filename, (unsigned long)iline, tk);
     56       return res;
     57     }
     58   }
     59   if(i < 4) {
     60     fprintf(stderr,
     61       "%s:%lu: not enough optical properties.\n"
     62       "Expect 4 parameters while %d is submitted - `%s'.\n",
     63       filename, (unsigned long)iline, i, str);
     64     return RES_BAD_ARG;
     65   }
     66 
     67   out_props->W  = props[0];
     68   out_props->Ne = props[3];
     69   out_props->Nr = props[1] / out_props->Ne; /* Absolute to relative */
     70   out_props->Kr = props[2] / out_props->Ne; /* Absolute to relative */
     71   if(!schiff_optical_properties_check(out_props)) {
     72     fprintf(stderr, "%s:%lu: invalid optical properties `%s'.\n",
     73       filename, (unsigned long)iline, str);
     74     return RES_BAD_ARG;
     75   }
     76   return RES_OK;
     77 }
     78 
     79 static FINLINE int
     80 cmp_properties(const void* op0, const void* op1)
     81 {
     82   const struct schiff_optical_properties* prop0 = op0;
     83   const struct schiff_optical_properties* prop1 = op1;
     84   return prop0->W < prop1->W ? -1 : (prop0->W > prop1->W ? 1 : 0);
     85 }
     86 
     87 static FINLINE int
     88 cmp_wavelength_to_properties(const void* wavelength, const void* op)
     89 {
     90   const double* W = wavelength;
     91   const struct schiff_optical_properties* prop = op;
     92   return *W < prop->W ? -1 : (*W > prop->W ? 1 : 0);
     93 }
     94 
     95 /*******************************************************************************
     96  * Local function
     97  ******************************************************************************/
     98 res_T
     99 schiff_optical_properties_load
    100   (struct schiff_optical_properties** props, const char* filename)
    101 {
    102   FILE* fp = NULL;
    103   res_T res = RES_OK;
    104   ASSERT(filename && props);
    105 
    106   fp = fopen(filename, "r");
    107   if(!fp) {
    108     fprintf(stderr, "Cannot open the file of optical properties `%s'.\n",
    109       filename);
    110     res = RES_IO_ERR;
    111     goto error;
    112   }
    113 
    114   res = schiff_optical_properties_load_stream(props, fp, filename);
    115   if(res != RES_OK) goto error;
    116 
    117 exit:
    118   if(fp) fclose(fp);
    119   return res;
    120 error:
    121   goto exit;
    122 }
    123 
    124 res_T
    125 schiff_optical_properties_load_stream
    126   (struct schiff_optical_properties** out_props,
    127    FILE* stream,
    128    const char* stream_name)
    129 {
    130   struct schiff_optical_properties* props = NULL;
    131   struct schiff_streamline streamline;
    132   size_t iline;
    133   char* line;
    134   res_T res = RES_OK;
    135   ASSERT(out_props && stream && stream_name);
    136 
    137   schiff_streamline_init(&streamline);
    138 
    139   for(iline=1;
    140     (res = schiff_streamline_read(&streamline, stream, &line)) != RES_EOF;
    141     ++iline) {
    142     struct schiff_optical_properties tmp_props;
    143 
    144     if(strcspn(line, "# \t") == 0) /* Empty line */
    145       continue;
    146 
    147     /* Read optical properties */
    148     line = strtok(line, "#");
    149     res = parse_optical_properties(&tmp_props, stream_name, iline, line);
    150     if(res == RES_OK) { /* *NO* error */
    151       sa_push(props, tmp_props);
    152     }
    153   }
    154 
    155   /* Sort the optical properties in ascending order with respect to the
    156    * wavelength */
    157   qsort(props, sa_size(props),
    158     sizeof(struct schiff_optical_properties), cmp_properties);
    159 
    160   *out_props = props;
    161   schiff_streamline_release(&streamline);
    162   return RES_OK;
    163 }
    164 
    165 void
    166 schiff_optical_properties_fetch
    167   (struct schiff_optical_properties* properties, /* Stetchy array */
    168    const double wavelength,
    169    struct sschiff_material_properties* props)
    170 {
    171   const size_t nproperties = sa_size(properties);
    172   struct schiff_optical_properties* find;
    173   double Ne, Kr, Nr;
    174   ASSERT(properties && props && wavelength > 0.0);
    175 
    176   /* Assume that properties are sorted in ascending order with respect to the
    177    * wavelength. */
    178   find = search_lower_bound(&wavelength, properties, nproperties,
    179     sizeof(struct schiff_optical_properties), cmp_wavelength_to_properties);
    180   ASSERT(!find || find->W >= wavelength);
    181 
    182   if(!find) /* Clamp to upper wavelength */
    183     find = properties + (nproperties - 1);
    184 
    185   if(find == properties || find == (properties + (nproperties - 1))
    186   || eq_eps(find->W, wavelength, 1.e-12)) {
    187     Ne = find[0].Ne;
    188     Kr = find[0].Kr;
    189     Nr = find[0].Nr;
    190   } else { /* Linear interpolation of optical properties */
    191     const double d = find[0].W - find[-1].W;
    192     const double u = (wavelength - find[-1].W) / d;
    193     const double v = 1.0 - u;
    194     Ne = u * find[0].Ne + v * find[-1].Ne;
    195     Kr = u * find[0].Kr + v * find[-1].Kr;
    196     Nr = u * find[0].Nr + v * find[-1].Nr;
    197   }
    198 
    199   props->medium_refractive_index = Ne;
    200   props->relative_imaginary_refractive_index = Kr;
    201   props->relative_real_refractive_index = Nr;
    202 }
    203