Commit 0ef519a4a62c88829271fa984c25fd465b707890

Authored by David Mayerich
1 parent 7c246292

optimized material class, still have to add KK

math/complex.h
... ... @@ -294,6 +294,19 @@ struct complex
294 294 return false;
295 295 }
296 296  
  297 + CUDA_CALLABLE bool operator<(complex<T> rhs){
  298 + return abs() < rhs.abs();
  299 + }
  300 + CUDA_CALLABLE bool operator<=(complex<T> rhs){
  301 + return abs() <= rhs.abs();
  302 + }
  303 + CUDA_CALLABLE bool operator>(complex<T> rhs){
  304 + return abs() > rhs.abs();
  305 + }
  306 + CUDA_CALLABLE bool operator >=(complex<T> rhs){
  307 + return abs() >= rhs.abs();
  308 + }
  309 +
297 310 //CASTING operators
298 311 template < typename otherT >
299 312 operator complex<otherT>()
... ... @@ -469,6 +482,20 @@ std::ostream&amp; operator&lt;&lt;(std::ostream&amp; os, rts::complex&lt;A&gt; x)
469 482 return os;
470 483 }
471 484  
  485 +template<class A>
  486 +std::istream& operator>>(std::istream& is, rts::complex<A>& x)
  487 +{
  488 + A r, i;
  489 + r = i = 0; //initialize the real and imaginary parts to zero
  490 + is>>r; //parse
  491 + is>>i;
  492 +
  493 + x.real(r); //assign the parsed values to x
  494 + x.imag(i);
  495 +
  496 + return is; //return the stream
  497 +}
  498 +
472 499 //#if __GNUC__ > 3 && __GNUC_MINOR__ > 7
473 500 //template<class T> using rtsComplex = rts::complex<T>;
474 501 //#endif
... ...
math/function.h
... ... @@ -2,6 +2,7 @@
2 2 #define RTS_FUNCTION_H
3 3  
4 4 #include <string>
  5 +#include <cmath>
5 6  
6 7 namespace rts{
7 8  
... ... @@ -9,8 +10,12 @@ namespace rts{
9 10 template <class Tx, class Ty>
10 11 class function
11 12 {
  13 +protected:
  14 +
12 15 std::vector<Tx> X;
13 16 std::vector<Ty> Y;
  17 + Ty range[2];
  18 + Ty bounding[2];
14 19  
15 20 //comparison function for searching lambda
16 21 static bool findCeiling(Tx ax, Tx bx){
... ... @@ -21,11 +26,6 @@ class function
21 26 void process_string(std::string s){
22 27 std::stringstream ss(s);
23 28  
24   - //std::string test;
25   - //std::getline(ss, test);
26   - //std::cout<<test;
27   - //exit(1);
28   -
29 29 Tx x;
30 30 Ty y;
31 31 std::string line;
... ... @@ -40,21 +40,36 @@ class function
40 40 lstream>>x; //read the x value
41 41 lstream>>y; //read the y value
42 42  
43   - //std::cout<<x<<", "<<y<<std::endl;
44   -
45 43 if(ss.eof()) break;
46 44 insert(x, y); //insert the read value into the function
47   -
48 45 }
49 46 }
50 47  
  48 + void update_range(Ty y){
  49 + //if the function is empty, just set the range to the given value
  50 + if(X.size() == 0){
  51 + range[0] = range[1] = y;
  52 + }
  53 +
  54 + //otherwise compare the values and set them appropriately
  55 + if(y < range[0]) range[0] = y;
  56 + if(y > range[1]) range[1] = y;
  57 + }
  58 +
51 59  
52 60 public:
  61 + function(){
  62 + range[0] = range[1] = NAN;
  63 + bounding[0] = bounding[1] = 0;
  64 + }
53 65  
54 66 //linear interpolation
55 67 Ty linear(Tx x) const
56 68 {
57   - if(X.size() == 0) return (Ty)0; //return zero if the function is empty
  69 + if(X.size() == 0) return bounding[0]; //return zero if the function is empty
  70 + //return bounding values if x is outside the sample domain
  71 + if(x < X[0]) return bounding[0];
  72 + if(x > X.back()) return bounding[1];
58 73  
59 74 unsigned int N = X.size(); //number of sample points
60 75  
... ... @@ -92,6 +107,8 @@ public:
92 107 {
93 108 unsigned int N = X.size(); //number of sample points
94 109  
  110 + update_range(y); //update the range of the function
  111 +
95 112 if(N == 0 || X[N-1] < x){
96 113 X.push_back(x);
97 114 Y.push_back(y);
... ... @@ -172,14 +189,30 @@ public:
172 189 }
173 190  
174 191  
175   -
  192 + //output a string description of the function (used for console output and debugging)
176 193 std::string str(){
177   - stringstream ss;
  194 + unsigned int N = X.size();
  195 +
  196 + std::stringstream ss;
  197 + ss<<"# of samples: "<<N<<std::endl;
  198 +
  199 + if(N == 0) return ss.str();
  200 +
  201 + ss<<"domain: ["<<X[0]<<", "<<X[X.size()-1]<<"]"<<std::endl;
  202 + ss<<"range: ["<<range[0]<<", "<<range[1]<<"]"<<std::endl;
  203 +
  204 +
  205 + return ss.str();
  206 +
  207 + }
  208 + std::string str_vals(){
  209 + std::stringstream ss;
178 210  
179 211 unsigned int N = X.size(); //number of sample points
180 212 //output each function value
181 213 for(unsigned int i = 0; i<N; i++){
182   - ss<<X[i]<<", "<<Y[i]<<std::endl;
  214 + if(i != 0) ss<<std::endl;
  215 + ss<<X[i]<<", "<<Y[i];
183 216 }
184 217  
185 218 return ss.str();
... ...
optics/material.h
1   -#ifndef MATERIALSTRUCT_H
2   -#define MATERIALSTRUCT_H
  1 +#ifndef RTS_MATERIAL_H
  2 +#define RTS_MATERIAL_H
3 3  
4 4 #include <vector>
5 5 #include <ostream>
... ... @@ -9,596 +9,145 @@
9 9 #include <algorithm>
10 10 #include <sstream>
11 11 #include "rts/math/complex.h"
  12 +#include "rts/math/constants.h"
12 13 #include "rts/math/function.h"
13 14  
14   -#define PI 3.14159f
15   -
16 15 namespace rts{
17 16  
18   - enum field_type {field_microns, field_wavenumber, field_n, field_k, field_A, field_ignore};
19   -
20   - //conversion functions
21   -
22   - //convert wavenumber to lambda
23   - template <class T>
24   - static T _wn(T inverse_cm)
25   - {
26   - return (T)10000.0/inverse_cm;
27   - }
  17 +//Material class - default representation for the material property is the refractive index (RI)
  18 +template<typename T>
  19 +class material : public function< T, complex<T> >{
28 20  
29   - template <class T>
30   - static T _2wn(T lambda)
31   - {
32   - return (T)10000.0/lambda;
33   - }
  21 +public:
  22 + enum wave_property{microns, inverse_cm};
  23 + enum material_property{ri, absorbance};
34 24  
35   - //convert absorbance to k
36   - template <class T>
37   - static T _A(T absorbance, T lambda)
38   - {
39   - return (absorbance * lambda) / (4 * PI);
40   - }
41   - template <class T>
42   - static T _2A(T k, T lambda)
43   - {
44   - return (4 * PI * k)/lambda;
45   - }
  25 +private:
46 26  
47   - //define the dispersion as a single wavelength/refractive index pair
48   - template <class T>
49   - struct refIndex
50   - {
51   - //wavelength (in microns)
52   - T lambda;
53   - complex<T> n;
54   - };
55   -
56   - template <class T>
57   - struct entryType
58   - {
59   - //list of value types per entry
60   - std::vector<field_type> valueList;
61   -
62   - entryType(std::string format)
63   - {
64   - //location of the end of a parameter
65   - size_t e;
66   -
67   - //string storing a token
68   - std::string token;
69   -
70   - do
71   - {
72   - //find the end of the first parameter
73   - e = format.find_first_of(',');
74   -
75   - //get the substring up to the comma
76   - token = format.substr(0, e);
77   -
78   - //turn the token into a val_type
79   - if(token == "microns")
80   - valueList.push_back(field_microns);
81   - else if(token == "wavenumber")
82   - valueList.push_back(field_wavenumber);
83   - else if(token == "n")
84   - valueList.push_back(field_n);
85   - else if(token == "k")
86   - valueList.push_back(field_k);
87   - else if(token == "A")
88   - valueList.push_back(field_A);
89   - else
90   - valueList.push_back(field_ignore);
91   -
92   - //remove the first token from the format string
93   - format = format.substr(e+1, format.length()-1);
94   - }while(e != std::string::npos);
95   -
96   -
97   -
98   - }
99   -
100   - void addValue(field_type value)
101   - {
102   - valueList.push_back(value);
103   - }
104   -
105   - refIndex<T> inputEntry(std::string line, T scaleA = 1.0)
106   - {
107   - T val;
108   - std::stringstream ss(line);
109   -
110   - //create a new refractive index
111   - refIndex<T> newRI;
112   -
113   -
114   - //read the entry from an input string
115   - for(unsigned int i=0; i<valueList.size(); i++)
116   - {
117   -
118   -
119   - while(ss.peek() < '0' || ss.peek() > '9')
120   - {
121   - //cout<<"bad char"<<endl;
122   - ss.ignore();
123   - }
124   -
125   - //retrieve the value
126   - ss>>val;
127   - //cout<<val<<endl;
128   -
129   - //store the value in the appropriate location
130   - switch(valueList[i])
131   - {
132   - case field_microns:
133   - newRI.lambda = val;
134   - break;
135   - case field_wavenumber:
136   - newRI.lambda = _wn(val);
137   - break;
138   - case field_n:
139   - newRI.n.real(val);
140   - break;
141   - case field_k:
142   - newRI.n.imag(val);
143   - break;
144   - case field_A:
145   - newRI.n.imag(_A(val * scaleA, newRI.lambda));
146   - break;
147   - default:
148   - break;
149   - }
150   - }
151   -
152   - //return the refractive index associated with the entry
153   - return newRI;
154   -
155   - }
156   -
157   - std::string outputEntry(refIndex<T> material)
158   - {
159   - //std::string result;
160   - std::stringstream ss;
161   -
162   - //for each field in the entry
163   - for(int i=0; i<valueList.size(); i++)
164   - {
165   - if(i > 0)
166   - ss<<"\t";
167   - //store the value in the appropriate location
168   - switch(valueList[i])
169   - {
170   - case field_microns:
171   - ss<<material.lambda;
172   - break;
173   - case field_wavenumber:
174   - ss<<_2wn(material.lambda);
175   - break;
176   - case field_n:
177   - ss<<material.n.real();
178   - break;
179   - case field_k:
180   - ss<<material.n.imag();
181   - break;
182   - case field_A:
183   - ss<<_2A(material.n.imag(), material.lambda);
184   - break;
185   - }
  27 + using function< T, complex<T> >::X;
  28 + using function< T, complex<T> >::Y;
  29 + using function< T, complex<T> >::insert;
  30 + using function< T, complex<T> >::bounding;
186 31  
187   - }
188   - return ss.str();
189   - }
  32 + std::string name; //name for the material (defaults to file name)
190 33  
  34 + void process_header(std::string str, wave_property& wp, material_property& mp){
191 35  
192   - };
193   -
194   -
195   - //a material is a list of refractive index values
196   - template <class T>
197   - class material
198   - {
199   - std::string name;
200   - //dispersion (refractive index as a function of wavelength)
201   - //std::vector< refIndex<T> > dispersion;
202   - function< T, complex<T> > dispersion;
203   -
204   - //average refractive index (approximately 1.4)
205   - T n0;
206   -
207   - /*void add(refIndex<T> ri)
208   - {
209   - //refIndex<T> converted = convert(ri, measurement);
210   - dispersion.push_back(ri);
211   - }*/
212   -
213   - //comparison function for sorting
214   - static bool compare(refIndex<T> a, refIndex<T> b)
215   - {
216   - return (a.lambda < b.lambda);
217   - }
218   -
219   - //comparison function for searching lambda
220   - /*static bool findCeiling(refIndex<T> a, refIndex<T> b)
221   - {
222   - return (a.lambda > b.lambda);
223   - }*/
224   -
225   - public:
226   - void add(T lambda, complex<T> n)
227   - {
228   - dispersion.insert(lambda, n);
229   - }
230   -
231   - std::string getName()
232   - {
233   - return name;
234   - }
235   - void setName(std::string n)
236   - {
237   - name = n;
238   - }
239   - T getN0()
240   - {
241   - return n0;
242   - }
243   - void setN0(T n)
244   - {
245   - n0 = n;
246   - }
  36 + std::stringstream ss(str); //create a stream from the data string
  37 + std::string line;
  38 + std::getline(ss, line); //get the first line as a string
  39 + while(line[0] == '#'){ //continue looping while the line is a comment
247 40  
248   - void setM(function< T, complex<T> > m)
249   - {
250   - dispersion = m;
251   - }
252   - unsigned int nSamples()
253   - {
254   - return dispersion.size();
255   - }
256   - material<T> computeN(T _n0, unsigned int n_samples = 0, T pf = 2)
257   - {
258   - /* This function computes the real part of the refractive index
259   - from the imaginary part. The Hilbert transform is required. I
260   - use an FFT in order to simplify this, so either the FFTW or CUFFT
261   - packages are required. CUFFT is used if this file is passed through
262   - a CUDA compiler. Otherwise, FFTW is used if available.
263   - */
264   -
265   - n0 = _n0;
266   -
267   - int N;
268   - if(n_samples)
269   - N = n_samples;
270   - else
271   - N = dispersion.size();
272   -
273   -
274   -#ifdef FFTW_AVAILABLE
275   - //allocate memory for the FFT
276   - complex<T>* Chi2 = (complex<T>*)fftw_malloc(sizeof(complex<T>) * N * pf);
277   - complex<T>* Chi2FFT = (complex<T>*)fftw_malloc(sizeof(complex<T>) * N * pf);
278   - complex<T>* Chi1 = (complex<T>*)fftw_malloc(sizeof(complex<T>) * N * pf);
279   -
280   - //create an FFT plan for the forward and inverse transforms
281   - fftw_plan planForward, planInverse;
282   - planForward = fftw_plan_dft_1d(N*pf, (fftw_complex*)Chi2, (fftw_complex*)Chi2FFT, FFTW_FORWARD, FFTW_ESTIMATE);
283   - planInverse = fftw_plan_dft_1d(N*pf, (fftw_complex*)Chi2FFT, (fftw_complex*)Chi1, FFTW_BACKWARD, FFTW_ESTIMATE);
284   -
285   - float k, alpha;
286   - T chi_temp;
287   -
288   - //the spectrum will be re-sampled in uniform values of wavenumber
289   - T nuMin = _2wn(dispersion.back().lambda);
290   - T nuMax = _2wn(dispersion.front().lambda);
291   - T dnu = (nuMax - nuMin)/(N-1);
292   - T lambda, tlambda;
293   - for(int i=0; i<N; i++)
294   - {
295   - //go from back-to-front (wavenumber is the inverse of wavelength)
296   - lambda = _wn(nuMax - i * dnu);
297   -
298   - //compute the frequency
299   - k = 2 * PI / (lambda);
300   -
301   - //get the absorbance
302   - alpha = getN(lambda).imag() * (2 * k);
303   -
304   - //compute chi2
305   - Chi2[i] = -alpha * (n0 / k);
306   - }
  41 + std::stringstream lstream(line); //create a stream from the line
  42 + lstream.ignore(); //ignore the first character ('#')
307 43  
308   - //use linear interpolation between the start and end points to pad the spectrum
309   - //complex<T> nMin = dispersion.back();
310   - //complex<T> nMax = dispersion.front();
311   - T a;
312   - for(int i=N; i<N*pf; i++)
313   - {
314   - //a = (T)(i-N)/(T)(N*pf - N);
315   - //Chi2[i] = a * Chi2[0] + ((T)1 - a) * Chi2[N-1];
  44 + std::string prop; //get the property name
  45 + lstream>>prop;
316 46  
317   - Chi2[i] = 0.0;//Chi2[N-1];
  47 + if(prop == "X"){
  48 + std::string wp_name;
  49 + lstream>>wp_name;
  50 + if(wp_name == "microns") wp = microns;
  51 + else if(wp_name == "inverse_cm") wp = inverse_cm;
318 52 }
319   -
320   - //perform the FFT
321   - fftw_execute(planForward);
322   -
323   - //perform the Hilbert transform in the Fourier domain
324   - complex<T> j(0, 1);
325   - for(int i=0; i<N*pf; i++)
326   - {
327   - //if w = 0, set the DC component to zero
328   - if(i == 0)
329   - Chi2FFT[i] *= (T)0.0;
330   - //if w <0, multiply by i
331   - else if(i < N*pf/2.0)
332   - Chi2FFT[i] *= j;
333   - //if i > N/2, multiply by -i
334   - else
335   - Chi2FFT[i] *= -j;
  53 + else if(prop == "Y"){
  54 + std::string mp_name;
  55 + lstream>>mp_name;
  56 + if(mp_name == "ri") mp = ri;
  57 + else if(mp_name == "absorbance") mp = absorbance;
336 58 }
337 59  
338   - //execute the inverse Fourier transform (completing the Hilbert transform)
339   - fftw_execute(planInverse);
340   -
341   - //divide the Chi1 values by N
342   - for(int i=0; i<N*pf; i++)
343   - Chi1[i] /= (T)(N*pf);
344   -
345   - //create a new material
346   - material<T> newM;
347   - newM.dispersion.clear();
348   - refIndex<T> ri;
349   - for(int i=0; i<N; i++)
350   - {
351   - ri.lambda = _wn(nuMax - i * dnu);
352   - ri.n.real(Chi1[i].real() / (2 * n0) + n0);
353   - ri.n.imag(getN(ri.lambda).imag());
354   -
355   - newM.dispersion.push_back(ri);
356   - }
357   -
358   -
359   - //dispersion[i].n.real(Chi1[i].real() / (2 * n0) + n0);
360   -
361   -
362   - /*//output the Absorbance value
363   - ofstream outOrig("origN.txt");
364   - for(int i=0; i<N; i++)
365   - outOrig<<dispersion[i].lambda<<" "<<dispersion[i].n.real()<<endl;
366   -
367   - //output the Chi2 value
368   - ofstream outChi2("chi2.txt");
369   - for(int i=0; i<N; i++)
370   - outChi2<<dispersion[i].lambda<<" "<<Chi2[i].real()<<endl;
371   -
372   - //output the Fourier transform
373   - ofstream outFFT("chi2_FFT.txt");
374   - for(int i=0; i<N; i++)
375   - {
376   - float mag = std::sqrt( std::pow(Chi2FFT[i].real(), 2.0) + std::pow(Chi2FFT[i].imag(), 2.0));
377   - outFFT<<dispersion[i].lambda<<" "<<mag<<endl;
378   - }
  60 + std::getline(ss, line); //get the next line
  61 + }
379 62  
380   - //output the computed Chi1 value
381   - ofstream outChi1("chi1.txt");
382   - for(int i=0; i<N; i++)
383   - {
384   - outChi1<<dispersion[i].lambda<<" "<<Chi1[i].real()<<" "<<Chi1[i].imag()<<endl;
385   - }
  63 + function< T, rts::complex<T> >::process_string(str);
  64 + }
386 65  
387   - ofstream outN("n.txt");
388   - for(int i=0; i<N; i++)
389   - outN<<dispersion[i].lambda<<" "<<Chi1[i].real() / (2 * n0) + n0<<endl;*/
  66 + void from_inverse_cm(){
  67 + //convert inverse centimeters to wavelength (in microns)
  68 + for(unsigned int i=0; i<X.size(); i++)
  69 + X[i] = 10000 / X[i];
390 70  
  71 + //reverse the function array
  72 + std::reverse(X.begin(), X.end());
  73 + std::reverse(Y.begin(), Y.end());
391 74  
392   - //de-allocate memory
393   - fftw_destroy_plan(planForward);
394   - fftw_destroy_plan(planInverse);
395   - fftw_free(Chi2);
396   - fftw_free(Chi2FFT);
397   - fftw_free(Chi1);
  75 + }
398 76  
399   - return newM;
400   -#else
401   - std::cout<<"MATERIAL Error: Must have FFTW in order to compute Kramers-Kronig."<<std::endl;
402   - return material<T>();
403   -#endif
404   - }
  77 + void init(){
  78 + bounding[0] = bounding[1] = rts::complex<T>(1, 0);
  79 + }
405 80  
406   - material(T lambda = 1, T n = 1, T k = 0)
407   - {
408   - dispersion.insert(lambda, complex<T>(n, k));
409   - /*//create a default refractive index
410   - refIndex<T> def;
411   - def.lambda = lambda;
412   - def.n.real(n);
413   - def.n.imag(k);
414   - add(def);
415   - */
416   - //set n0
417   - n0 = 0;
418   - }
419   -
420   - material(std::string filename, std::string format = "", T scaleA = 1.0)
421   - {
422   - fromFile(filename, format);
423   - n0 = 0;
424   - }
425   -
426   - void fromFile(std::string filename, std::string format = "", T scaleA = 1.0)
427   - {
428   - name = filename;
429   - //clear any previous values
430   - dispersion = rts::function< T, complex<T> >();
431   -
432   - //load the file into a string
433   - std::ifstream ifs(filename.c_str());
434   -
435   - std::string line;
436   -
437   - if(!ifs.is_open())
438   - {
439   - std::cout<<"Material Error -- file not found: "<<filename<<std::endl;
440   - exit(1);
441   - }
442   -
443   - //process the file as a string
444   - std::string instr((std::istreambuf_iterator<char>(ifs)), std::istreambuf_iterator<char>());
445   - fromStr(instr, format, scaleA);
446   - }
447   -
448   - void fromStr(std::string str, std::string format = "", T scaleA = 1.0)
449   - {
450   - //create a string stream to process the input data
451   - std::stringstream ss(str);
452   -
453   - //this string will be read line-by-line (where each line is an entry)
454   - std::string line;
455   -
456   - //if the format is not provided, see if it is in the file, otherwise use a default
457   - if(format == "")
458   - {
459   - //set a default format of "lambda,n,k"
460   - format = "microns,n,k";
461   -
462   - //see if the first line is a comment
463   - char c = ss.peek();
464   - if(c == '#')
465   - {
466   - //get the first line
467   - getline(ss, line);
468   - //look for a bracket, denoting the start of a format string
469   - int istart = line.find('[');
470   - if(istart != std::string::npos)
471   - {
472   - //look for a bracket terminating the format string
473   - int iend = line.find(']');
474   - if(iend != std::string::npos)
475   - {
476   - //read the string between the brackets
477   - format = line.substr(istart+1, iend - istart - 1);
478   - }
479   - }
480   - }
481   -
482   - }
483   -
484   - entryType<T> entry(format);
485   -
486   - //std::cout<<"Loading material with format: "<<format<<std::endl;
487   -
488   - while(!ss.eof())
489   - {
490   - //read a line from the string
491   - getline(ss, line);
492   -
493   - //if the line is not a comment, process it
494   - if(line[0] != '#')
495   - {
496   - //load the entry and add it to the dispersion list
497   - add(entry.inputEntry(line, scaleA).lambda, entry.inputEntry(line, scaleA).n);
498   - }
499   - //generally have to peek to trigger the eof flag
500   - ss.peek();
501   - }
502   -
503   - //sort the vector by lambda
504   - //sort(dispersion.begin(), dispersion.end(), &material<T>::compare);
505   - }
506   -
507   - //convert the material to a string
508   - std::string toStr(std::string format = "microns,n,k", bool reverse_order = false)
509   - {
510   - std::stringstream ss;
511   - entryType<T> entry(format);
512   -
513   - if(reverse_order)
514   - {
515   - for(int l=dispersion.size() - 1; l>=0; l--)
516   - {
517   - if(l < dispersion.size() - 1) ss<<std::endl;
518   - ss<<entry.outputEntry(dispersion[l]);
519   - }
520 81  
521   - }
522   - else
523   - {
524   - for(unsigned int l=0; l<dispersion.size(); l++)
525   - {
526   - if(l > 0) ss<<std::endl;
527   - ss<<entry.outputEntry(dispersion[l]);
528   - }
529   - }
530   -
531   - return ss.str();
532   - }
533   -
534   - void save(std::string filename, std::string format = "microns,n,k", bool reverse_order = false)
535   - {
536   - std::ofstream outfile(filename.c_str());
537   - outfile<<"#material file saved as [" + format + "]"<<std::endl;
538   - outfile<<toStr(format, reverse_order)<<std::endl;
539   -
540   - }
541   -
542   - //convert between wavelength and wavenumber
543   - /*void nu2lambda(T s = (T)1)
544   - {
545   - for(int i=0; i<dispersion.size(); i++)
546   - dispersion[i].lambda = s/dispersion[i].lambda;
547   - }
548   -
549   - void lambda2nu(T s = (T)1)
550   - {
551   - for(int i=0; i<dispersion.size(); i++)
552   - dispersion[i].lambda = s/dispersion[i].lambda;
553   - }*/
554   -
555   -
556   - refIndex<T>& operator[](unsigned int i)
557   - {
558   - return dispersion[i];
  82 +public:
559 83  
560   - }
  84 + material(std::string filename, wave_property wp, material_property mp){
  85 + name = filename;
  86 + load(filename, wp, mp);
  87 + }
561 88  
562   - complex<T> getN(T l)
563   - {
564   - //return complex<T>(1.0, 0.0);
565   - complex<T> ri = dispersion.linear(l) + n0;
566   - return ri;
567   - }
  89 + material(std::string filename){
  90 + name = filename;
  91 + load(filename);
  92 + }
568 93  
569   - function<T, complex<T> > getF()
570   - {
571   - return dispersion + complex<T>(n0, 0.0);
572   - }
  94 + material(){
  95 + init();
  96 + }
573 97  
574   - //returns the scattering efficiency at wavelength l
575   - complex<T> eta(T l)
576   - {
577   - //get the refractive index
578   - complex<T> ri = getN(l);
  98 + complex<T> getN(T lambda){
  99 + return function< T, complex<T> >::linear(lambda);
  100 + }
579 101  
580   - //convert the refractive index to scattering efficiency
581   - return ri*ri - 1.0;
  102 + void load(std::string filename, wave_property wp, material_property mp){
582 103  
583   - }
584   - //interpolate the given lambda value and return the index of refraction
585   - complex<T> operator()(T l)
586   - {
587   - return getN(l);
588   - }
  104 + //load the file as a function
  105 + function< T, complex<T> >::load(filename);
  106 + }
589 107  
  108 + void load(std::string filename){
  109 +
  110 + wave_property wp = inverse_cm;
  111 + material_property mp = ri;
  112 + //turn the file into a string
  113 + std::ifstream t(filename.c_str()); //open the file as a stream
  114 +
  115 + if(!t){
  116 + std::cout<<"ERROR: Couldn't open the material file '"<<filename<<"'"<<std::endl;
  117 + exit(1);
  118 + }
  119 + std::string str((std::istreambuf_iterator<char>(t)),
  120 + std::istreambuf_iterator<char>());
  121 +
  122 + //process the header information
  123 + process_header(str, wp, mp);
  124 +
  125 + //convert units
  126 + if(wp == inverse_cm)
  127 + from_inverse_cm();
  128 + //set the bounding values
  129 + bounding[0] = Y[0];
  130 + bounding[1] = Y.back();
  131 + }
  132 + std::string str(){
  133 + std::stringstream ss;
  134 + ss<<name<<std::endl;
  135 + ss<<function< T, complex<T> >::str();
  136 + return ss.str();
  137 + }
  138 + std::string get_name(){
  139 + return name;
  140 + }
590 141  
591   - };
592   -} //end namespace rts
  142 + void set_name(std::string str){
  143 + name = str;
  144 + }
593 145  
594   -template <typename T>
595   -std::ostream& operator<<(std::ostream& os, rts::material<T> m)
596   -{
597   - os<<m.toStr();
  146 +};
598 147  
599   - return os;
600 148 }
601 149  
602 150  
603 151  
  152 +
604 153 #endif
... ...
optics/mirst-1d.cuh
1 1 #include "../optics/material.h"
2 2 #include "../math/complexfield.cuh"
  3 +#include "../math/constants.h"
3 4  
4 5 #include "cufft.h"
5 6  
... ... @@ -51,7 +52,7 @@ __global__ void gpu_mirst1d_layer_fft(complex&lt;T&gt;* dest, complex&lt;T&gt;* ri,
51 52  
52 53 //T l = w * ri[inu].real();
53 54 //complex<T> e(0.0, -2 * PI * fz * (zf[inu] + zR/2 - l/2.0));
54   - complex<T> e(0, -2 * PI * fz * (zf[inu] + opl/2));
  55 + complex<T> e(0, -2 * rtsPI * fz * (zf[inu] + opl/2));
55 56  
56 57 complex<T> eta = ri[inu] * ri[inu] - 1;
57 58  
... ... @@ -59,7 +60,7 @@ __global__ void gpu_mirst1d_layer_fft(complex&lt;T&gt;* dest, complex&lt;T&gt;* ri,
59 60 if(ifz == 0)
60 61 dest[i] += opl * exp(e) * eta * src[inu];
61 62 else
62   - dest[i] += opl * exp(e) * eta * src[inu] * sin(PI * fz * opl) / (PI * fz * opl);
  63 + dest[i] += opl * exp(e) * eta * src[inu] * sin(rtsPI * fz * opl) / (rtsPI * fz * opl);
63 64 }
64 65  
65 66 template<typename T>
... ... @@ -139,7 +140,7 @@ __global__ void gpu_mirst1d_apply_filter(complex&lt;T&gt;* sampleFFT, T* lambda,
139 140 //compute the final filter
140 141 T mirst = 0;
141 142 if(fz != 0)
142   - mirst = 2 * PI * r * s * Q * (1/fz);
  143 + mirst = 2 * rtsPI * r * s * Q * (1/fz);
143 144  
144 145 sampleFFT[i] *= mirst;
145 146  
... ... @@ -246,7 +247,7 @@ private:
246 247 //store the refractive index and source profile in a CPU array
247 248 for(int inu=0; inu<S; inu++){
248 249 //save the refractive index to the GPU
249   - ri = matlist[n].getN(lambdas[inu]);
  250 + ri = matlist[n].getN(lambdas[inu]);
250 251 HANDLE_ERROR(cudaMemcpy( gpuRi + inu, &ri, sizeof(complex<T>), cudaMemcpyHostToDevice ));
251 252  
252 253 //save the source profile to the GPU
... ... @@ -320,6 +321,7 @@ public:
320 321 pad = padding;
321 322 NA[0] = 0;
322 323 NA[1] = 0.8;
  324 + S = 0;
323 325 }
324 326  
325 327 //add a layer, thickness = microns
... ... @@ -397,16 +399,17 @@ public:
397 399 std::string str(){
398 400  
399 401 stringstream ss;
400   -
  402 + ss<<"1D MIRST Simulation========================="<<std::endl;
401 403 ss<<"z-axis resolution: "<<Z<<std::endl;
  404 + ss<<"simulation domain: ["<<lambdas[0]<<", "<<lambdas.back()<<"]"<<std::endl;
402 405 ss<<"number of wavelengths: "<<lambdas.size()<<std::endl;
403 406 ss<<"padding: "<<pad<<std::endl;
404 407 ss<<"sample thickness: "<<thickness()<<" um"<<std::endl;
405 408 ss<<"dz: "<<dz()<<" um"<<std::endl;
406 409 ss<<std::endl;
407   - ss<<"layers: "<<layers.size()<<" -----------------"<<std::endl;
  410 + ss<<layers.size()<<" layers-------------"<<std::endl;
408 411 for(unsigned int l=0; l<layers.size(); l++)
409   - ss<<"layer "<<l<<": "<<layers[l]<<" um"<<" ("<<matlist[l].getName()<<")"<<std::endl;
  412 + ss<<"layer "<<l<<": "<<layers[l]<<" um"<<"---------"<<std::endl<<matlist[l].str()<<std::endl;
410 413  
411 414 return ss.str();
412 415  
... ... @@ -417,4 +420,4 @@ public:
417 420  
418 421 };
419 422  
420   -}
421 423 \ No newline at end of file
  424 +}
... ...
ui/arguments.h
... ... @@ -196,15 +196,15 @@ namespace rts{
196 196 if(d == 0)
197 197 ss<<desc[0];
198 198 else
199   - ss<<std::endl<<setfill(' ')<<setw(width)<<" "<<desc[d];
  199 + ss<<std::endl<<std::setfill(' ')<<std::setw(width)<<" "<<desc[d];
200 200  
201 201 }
202 202  
203 203 //output the range in the right column
204 204 if(range != "" && ansi)
205   - ss<<std::endl<<setfill(' ')<<setw(width)<<" "<<" "<<std::string("setw(width)<<" "<<" "<<std::string("\033[1;36m") + range + "\033[0m";33[1;36m") + range + "setw(width)<<" "<<" "<<std::string("\033[1;36m") + range + "\033[0m";33[0m";
  205 + ss<<std::endl<<std::setfill(' ')<<std::setw(width)<<" "<<" "<<std::string("setw(width)<<" "<<" "<<std::string("\033[1;36m") + range + "\033[0m";33[1;36m") + range + "setw(width)<<" "<<" "<<std::string("\033[1;36m") + range + "\033[0m";33[0m";
206 206 else if(range != "")
207   - ss<<std::endl<<setfill(' ')<<setw(width)<<" "<<" "<<range;
  207 + ss<<std::endl<<std::setfill(' ')<<std::setw(width)<<" "<<" "<<range;
208 208  
209 209 return ss.str();
210 210 }
... ... @@ -253,7 +253,10 @@ namespace rts{
253 253  
254 254 public:
255 255  
256   - arglist(){ col_width = 0; }
  256 + arglist(){
  257 + col_width = 0;
  258 + ansi = true;
  259 + }
257 260  
258 261 void set_ansi(bool b)
259 262 {
... ... @@ -295,9 +298,9 @@ namespace rts{
295 298 if(si != -1 && a == sections[si].index)
296 299 {
297 300 if(ansi)
298   - ss<<std::endl<<std::left<<setfill('=')<<setw(col_width)<<std::string("setw(col_width)<<std::string("\033[1;31m") + sections[si].name<<"\033[0m"<<std::endl;33[1;31m") + sections[si].name<<"setw(col_width)<<std::string("\033[1;31m") + sections[si].name<<"\033[0m"<<std::endl;33[0m"<<std::endl;
  301 + ss<<std::endl<<std::left<<std::setfill('=')<<std::setw(col_width)<<std::string("setw(col_width)<<std::string("\033[1;31m") + sections[si].name<<"\033[0m"<<std::endl;33[1;31m") + sections[si].name<<"setw(col_width)<<std::string("\033[1;31m") + sections[si].name<<"\033[0m"<<std::endl;33[0m"<<std::endl;
299 302 else
300   - ss<<std::endl<<std::left<<setfill('=')<<setw(col_width)<<sections[si].name<<std::endl;
  303 + ss<<std::endl<<std::left<<std::setfill('=')<<std::setw(col_width)<<sections[si].name<<std::endl;
301 304 si++;
302 305 if(si == sections.size()) si = -1;
303 306 }
... ... @@ -326,7 +329,7 @@ namespace rts{
326 329 {
327 330 args[i].set(_value);
328 331 //adjust the column width if necessary
329   - col_width = max(col_width, args[i].col_width());
  332 + col_width = std::max(col_width, args[i].col_width());
330 333 }
331 334 else
332 335 std::cout<<"ERROR - Argument not recognized: "<<_name<<std::endl;
... ...