rl_raysuplib  1.0.13
rl_Multilayer_rdb.cc
1 // File: rl_Multilayer_rdb.cc
2 // Author: Terry Gaetz
3 
4 // --8<--8<--8<--8<--
5 //
6 // Copyright (C) 2006 Smithsonian Astrophysical Observatory
7 //
8 // This file is part of rl_ray
9 //
10 // rl_ray is free software; you can redistribute it and/or
11 // modify it under the terms of the GNU General Public License
12 // as published by the Free Software Foundation; either version 2
13 // of the License, or (at your option) any later version.
14 //
15 // rl_ray is distributed in the hope that it will be useful,
16 // but WITHOUT ANY WARRANTY; without even the implied warranty of
17 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 // GNU General Public License for more details.
19 //
20 // You should have received a copy of the GNU General Public License
21 // along with this program; if not, write to the
22 // Free Software Foundation, Inc.
23 // 51 Franklin Street, Fifth Floor
24 // Boston, MA 02110-1301, USA
25 //
26 // -->8-->8-->8-->8--
27 
28 #include <rl_Multilayer_rdb.h> // rl_Multilayer_rdb
29 
30 #include <rl_raylib/rl_Traits.h>
31 #include <rl_DielectricPOD_rdb.h> // rl_DielectricPOD_rdb
32 #include <tracefct/exiterrvals.h>
33 #include <tracefctxx/TraceFct.h>
34 
35 #include <cctype> // toupper
36 
37 
38 #include <mst_rdb/mst_rdb.h>
39 #include <suplib/str.h>
40 
41 //=========================================================================
42 // statics
43 
44 static TokListToken /* note: must be in lexical order */
45 srough_type[] =
46 {
47  { "DW_CSAO", rl_Traits::ERoughDebyeWaller_CSAO },
48  { "DW_RSAO", rl_Traits::ERoughDebyeWaller_RSAO },
49  { "DW_SPILLER", rl_Traits::ERoughDebyeWaller_Spiller },
50  { "MDW", rl_Traits::ERoughModifiedDebyeWaller },
51  { "NC", rl_Traits::ERoughNevotCroce },
52  { "NONE", rl_Traits::ERoughNone }
53 };
54 TokList srough_types = GenTokList( srough_type );
55 
56 //=========================================================================
57 // dtor, ctors
58 
59 rl_Multilayer_rdb::
60 ~rl_Multilayer_rdb()
61 {}
62 
63 //-------------------------------------------------------------------------
64 // Routine to set up surface data
65 
66 rl_Multilayer_rdb::
67 rl_Multilayer_rdb( char const rdb_filename[],
68  rl_Traits::EInterpMode interp_mode
69  )
70  : rl_Multilayer(0,0)
71 {
72  init_from_rdb( rdb_filename, interp_mode );
73 }
74 
75 //-------------------------------------------------------------------------
76 // function to read in data from multilayer rdb table
77 
78 void rl_Multilayer_rdb::
79 init_from_rdb( char const *rdb_filename_in,
80  rl_Traits::EInterpMode interp_mode
81  )
82 {
83  TraceFct tf("rl_Multilayer_rdb::init");
84 
85  own_data_ = rl_Traits::True;
86 
87  FILE *in;
88  rdbHeader *hdr;
89  DataColumnMap_st *map;
90 
91  long int nrow;
92  int num_fields = 0;
93 
94  typedef struct LayerRecord
95  {
96  char* material;
97  double thickness;
98  double bulkdensity;
99  char* roughness_type;
100  double srough;
101  char* optconst_rdb;
102  } LayerRecord;
103  LayerRecord layer_record;
104 
105  RDBFieldStInfo fields[6];
106 #if 0
107  {
108  RDBentry( material, RDB_String, LayerRecord ),
109  RDBentry( thickness, RDB_Num, LayerRecord ),
110  RDBentry( bulkdensity, RDB_Num, LayerRecord ),
111  RDBentry( optconst_rdb, RDB_String, LayerRecord ),
112  RDBentry( roughness_type, RDB_String, LayerRecord ),
113  RDBentry( srough, RDB_Num, LayerRecord )
114  };
115 #endif
116 
117  #define SET_FIELD(colname,var,vartype,idx) \
118  do{ \
119  fields[idx].name = #colname; \
120  fields[idx].type = vartype; \
121  fields[idx].offset = offsetof( LayerRecord, var ); \
122  idx++; \
123  }while(0)
124 
125  #define CHECK_FIELD(colname) \
126  if (! rdb_is_column( hdr, #colname ) ) \
127  { \
128  tf.die( "no \"" #colname "\"column in reflectance rdb file" ); \
129  }
130 
131  int error;
132  char *rdb_filename =
133  str_interp( rdb_filename_in, 1, NULL, NULL, &error );
134  if ( error )
135  tf.die( "error interpolating filename: %s", rdb_filename_in );
136 
137  if ( !(in=fopen( rdb_filename, "r" )) )
138  tf.exit( ExitERR_fopen, "unable to open input `%s'", rdb_filename );
139 
140  if (! (hdr = rdb_rd_hdr( in )) )
141  tf.die( "rdb file `%s' contains no rdb headers!", rdb_filename );
142 
143  CHECK_FIELD( material );
144  SET_FIELD( material, material, RDB_String, num_fields );
145 
146  CHECK_FIELD( thickness );
147  SET_FIELD( thickness, thickness, RDB_Num, num_fields );
148 
149  CHECK_FIELD( bulkdensity );
150  SET_FIELD( bulkdensity, bulkdensity, RDB_Num, num_fields );
151 
152  CHECK_FIELD( optconst_rdb );
153  SET_FIELD( optconst_rdb, optconst_rdb, RDB_String, num_fields );
154 
155  int have_roughness = 0;
156  if ( rdb_is_column( hdr, "roughness_type" ) )
157  {
158  have_roughness = 1;
159 
160  CHECK_FIELD( srough );
161  SET_FIELD( roughness_type, roughness_type, RDB_String, num_fields );
162  SET_FIELD( srough, srough, RDB_Num, num_fields );
163  }
164 
165  map = rdb_map_cols_stst( hdr, num_fields, fields );
166 
167  /*
168  * count number of rows (excluding header & comments) in rdb file
169  */
170  nrow = rdb_count(in, hdr);
171  if ( nrow < 0 )
172  tf.die( "multilayer rdb file '%s' is not rewindable" );
173  else if ( nrow == 0 )
174  tf.die(
175  "multilayer rdb file '%s' must have at least one row", rdb_filename );
176 
177  num_layers_ = nrow;
178 
179  layer_ = new rl_DielectricLayer[num_layers_];
180  if (! layer_ )
181  {
182  tf.exit(ExitERR_alloc, "unable to allocate rl_DielectricLayer array" );
183  }
184 
185  int n;
186  for ( n = 0 ; n < num_layers_ ; ++n )
187  {
188  rdb_col_read_st(in, hdr, map, &layer_record);
189  if (! (layer_record.bulkdensity >= 0.0) )
190  {
191  tf.die( "layer %d: must have bulk density >= 0.0" );
192  }
193  rl_DielectricPOD_rdb diel( layer_record.optconst_rdb );
194 
195  double srough = 0.0;
196  rl_Traits::ERoughType rtype = rl_Traits::ERoughNone;
197 
198  if ( have_roughness )
199  {
200  char* str = layer_record.roughness_type;
201  while ( *str )
202  {
203  *str = toupper(*str);
204  ++str;
205  }
206  int roughtype = tokmatch( layer_record.roughness_type, &srough_types );
207 
208  if ( roughtype >= 0 )
209  {
210  rtype = (rl_Traits::ERoughType)roughtype;
211  }
212  else
213  {
214  tf.die( "invalid \"roughness\" type %s", layer_record.roughness_type );
215  }
216  srough = layer_record.srough;
217  }
218 
219  rl_Traits::Bool substrate = rl_Traits::Bool((n == num_layers_-1) ? 1 : 0);
220 
221  layer_[n].init( diel.const_data_ptr(),
222  diel.num_elts(),
223  layer_record.thickness,
224  srough,
225  rtype,
226  interp_mode,
227  layer_record.bulkdensity,
228  layer_record.material,
229  substrate );
230 
231  delete layer_record.material;
232  delete layer_record.roughness_type;
233  delete layer_record.optconst_rdb;
234  }
235  // clean up
236 
237  free( rdb_filename );
238  rdb_free_map(map); // free up data column map
239  rdb_free_hdr(hdr); // free up rdbHeader dynamic allocation
240  fclose(in);
241 }
242 #undef SET_FIELD
243 #undef CHECK_FIELD
A class encapsulating reading of rl_DielectricPOD initialization data from an rdb table.