Blame view

SimulateSpectrum.cpp 15 KB
da3d4e0e   dmayerich   Initial commit.
1
2
3
4
5
  #include <math.h>
  #include <complex>
  #include <iostream>
  #include <fstream>
  #include "globals.h"
bfe3f56b   dmayerich   Fixed Linux compa...
6
  #include <stdlib.h>
da3d4e0e   dmayerich   Initial commit.
7
8
9
10
11
  //#include "cufft.h"
  using namespace std;
  
  #define pi 3.14159
  
52a5fe9d   dmayerich   Added double supp...
12
  typedef complex<double> scComplex;
da3d4e0e   dmayerich   Initial commit.
13
  
bfe3f56b   dmayerich   Fixed Linux compa...
14
  extern int cbessjyva(double v,complex<double> z,double &vm,complex<double>*cjv,
da3d4e0e   dmayerich   Initial commit.
15
      complex<double>*cyv,complex<double>*cjvp,complex<double>*cyvp);
bfe3f56b   dmayerich   Fixed Linux compa...
16
  extern int bessjyv(double v,double x,double &vm,double *jv,double *yv,
da3d4e0e   dmayerich   Initial commit.
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
      double *djv,double *dyv);
  
  complex<double> Jl_neg(complex<double> x)
  {
  	//this function computes the bessel function of the first kind Jl(x) for l = -0.5
  	return ( sqrt(2.0/pi) * cos(x) )/sqrt(x);
  }
  
  double Jl_neg(double x)
  {
  	//this function computes the bessel function of the first kind Jl(x) for l = -0.5
  	return ( sqrt(2.0/pi) * cos(x) )/sqrt(x);
  }
  
  double Yl_neg(double x)
  {
  	//this function computes the bessel function of the second kind Yl(x) for l = -0.5;
  	return ( sqrt(2.0/pi) * sin(x) )/sqrt(x);
  }
  
52a5fe9d   dmayerich   Added double supp...
37
  void computeB(complex<double>* B, double radius, complex<double> refIndex, double lambda, int Nl)
da3d4e0e   dmayerich   Initial commit.
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
  {
  	double k = (2*pi)/lambda;
  	int b = 2;
  
  	//allocate space for the real bessel functions
  	double* jv = (double*)malloc(sizeof(double)*(Nl+b));
  	double* yv = (double*)malloc(sizeof(double)*(Nl+b));
  	double* jvp = (double*)malloc(sizeof(double)*(Nl+b));
  	double* yvp = (double*)malloc(sizeof(double)*(Nl+b));
  
  	//allocate space for the complex bessel functions
  	complex<double>* cjv = (complex<double>*)malloc(sizeof(complex<double>)*(Nl+b));
  	complex<double>* cyv = (complex<double>*)malloc(sizeof(complex<double>)*(Nl+b));
  	complex<double>* cjvp = (complex<double>*)malloc(sizeof(complex<double>)*(Nl+b));
  	complex<double>* cyvp = (complex<double>*)malloc(sizeof(complex<double>)*(Nl+b));
  
  	double kr = k*radius;
  	complex<double> knr = k*refIndex*(double)radius;
  	complex<double> n = refIndex;
  
  	//compute the bessel functions for k*r
  	double vm;// = Nl - 1;
  	bessjyv((Nl)+0.5, kr, vm, jv, yv, jvp, yvp);
  	//cout<<"Nl: "<<Nl<<"  vm: "<<vm<<endl;
  	//printf("Nl: %f, vm: %f\n", (float)Nl, (float)vm);
  
  	//compute the bessel functions for k*n*r
  	cbessjyva((Nl)+0.5, knr, vm, cjv, cyv, cjvp, cyvp);
  
  	//scale factor for spherical bessel functions
  	double scale_kr = sqrt(pi/(2.0*kr));
  	complex<double> scale_knr = sqrt(pi/(2.0*knr));
  
  	complex<double> numer, denom;
  	double j_kr;
  	double y_kr;
  	complex<double> j_knr;
  	complex<double> j_d_knr;
  	double j_d_kr;
  	complex<double> h_kr;
  	complex<double> h_d_kr;
  	complex<double> h_neg;
  	complex<double> h_pos;
  
  	//cout<<"B coefficients:"<<endl;
  	for(int l=0; l<Nl; l++)
  	{
  		//compute the spherical bessel functions
  		j_kr = jv[l] * scale_kr;
  		y_kr = yv[l] * scale_kr;
  		j_knr = cjv[l] * scale_knr;
  
  		//compute the Hankel function
  		h_kr = complex<double>(j_kr, y_kr);
  
  		//compute the derivatives
  		if(l == 0)
  		{
  			//spherical bessel functions for l=0
  			j_d_kr = scale_kr * (Jl_neg(kr) - (jv[l] + kr*jv[l+1])/kr )/2.0;
  			j_d_knr = scale_knr * ( Jl_neg(knr) - (cjv[l] + knr*cjv[l+1])/knr )/2.0;
  			h_neg = complex<double>(scale_kr*Jl_neg(kr), scale_kr*Yl_neg(kr));
  			h_pos = complex<double>(scale_kr*jv[l+1], scale_kr*yv[l+1]);
  			h_d_kr = (h_neg - (h_kr + kr*h_pos)/kr)/2.0;
  		}
  		else
  		{
  			//spherical bessel functions
  			j_d_kr = scale_kr * (jv[l-1] - (jv[l] + kr*jv[l+1])/kr )/2.0;
  			j_d_knr = scale_knr * ( cjv[l-1] - (cjv[l] + knr*cjv[l+1])/knr )/2.0;
  			h_neg = complex<double>(scale_kr*jv[l-1], scale_kr*yv[l-1]);
  			h_pos = complex<double>(scale_kr*jv[l+1], scale_kr*yv[l+1]);
  			h_d_kr = (h_neg - (h_kr + kr*h_pos)/kr)/2.0;
  		}
  
  		numer = j_kr*j_d_knr*n - j_knr*j_d_kr;
  		denom = j_knr*h_d_kr - h_kr*j_d_knr*n;
52a5fe9d   dmayerich   Added double supp...
115
  		B[l] =  numer/denom;
da3d4e0e   dmayerich   Initial commit.
116
  
52a5fe9d   dmayerich   Added double supp...
117
  		//B[l] = scComplex(temp.real(), temp.imag());
da3d4e0e   dmayerich   Initial commit.
118
119
120
121
122
123
124
125
126
127
128
129
130
  		//cout<<B[l]<<endl;
  	}
  
  	free(jv);
  	free(yv);
  	free(jvp);
  	free(yvp);
  	free(cjv);
  	free(cyv);
  	free(cjvp);
  	free(cyvp);
  }
  
52a5fe9d   dmayerich   Added double supp...
131
  void Legendre(double* P, double x, int Nl)
da3d4e0e   dmayerich   Initial commit.
132
133
134
135
136
137
138
139
140
141
142
143
  {
  	//computes the legendre polynomials from orders 0 to Nl-1
  	P[0] = 1;
  	if(Nl == 1) return;
  	P[1] = x;
  	for(int l = 2; l < Nl; l++)
  	{
  		P[l] = ((2*l - 1)*x*P[l-1] - (l - 1)*P[l-2])/l;
  	}	
  
  }
  
52a5fe9d   dmayerich   Added double supp...
144
  complex<double> integrateUi(double cAngleI, double cAngleO, double oAngleI, double oAngleO, double M = 2*pi)
da3d4e0e   dmayerich   Initial commit.
145
146
147
148
149
150
151
152
153
  {
  	/*This function integrates the incident field of magnitude M in the far zone
  	in order to evaluate the field at the central pixel of a detector.
  	cNAi = condenser inner angle
  	cNAo = condenser outer angle
  	oNAi = objective inner angle
  	oNAo = objective outer angle
  	M = field magnitude*/
  
52a5fe9d   dmayerich   Added double supp...
154
155
  	double alphaIn = max(cAngleI, oAngleI);
  	double alphaOut = min(cAngleO,oAngleO);
da3d4e0e   dmayerich   Initial commit.
156
  
52a5fe9d   dmayerich   Added double supp...
157
  	complex<double> Ui;
da3d4e0e   dmayerich   Initial commit.
158
  	if(alphaIn > alphaOut)
52a5fe9d   dmayerich   Added double supp...
159
  		Ui = complex<double>(0.0, 0.0);
da3d4e0e   dmayerich   Initial commit.
160
  	else
52a5fe9d   dmayerich   Added double supp...
161
  		Ui = complex<double>(M * 2 * pi * (cos(alphaIn) - cos(alphaOut)), 0.0f);
da3d4e0e   dmayerich   Initial commit.
162
163
164
165
166
  
  	return Ui;
  
  }
  
52a5fe9d   dmayerich   Added double supp...
167
  void computeCondenserAlpha(double* alpha, int Nl, double cAngleI, double cAngleO)
da3d4e0e   dmayerich   Initial commit.
168
169
170
171
172
173
174
  {
  	/*This function computes the condenser integral in order to build the field of incident light
  	alpha = list of Nl floating point values representing the condenser alpha as a function of l
  	Nl = number of orders in the incident field
  	cAngleI, cAngleO = inner and outer condenser angles (inner and outer NA)*/
  
  	//compute the Legendre polynomials for the condenser aperature
52a5fe9d   dmayerich   Added double supp...
175
  	double* PcNAo = (double*)malloc(sizeof(double)*(Nl+1));
da3d4e0e   dmayerich   Initial commit.
176
  	Legendre(PcNAo, cos(cAngleO), Nl+1);
52a5fe9d   dmayerich   Added double supp...
177
  	double* PcNAi = (double*)malloc(sizeof(double)*(Nl+1));
da3d4e0e   dmayerich   Initial commit.
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
  	Legendre(PcNAi, cos(cAngleI), Nl+1);
  
  	for(int l=0; l<Nl; l++)
  	{
  		//integration term
  		if(l == 0)
  			alpha[l] = -PcNAo[l+1] + PcNAo[0] + PcNAi[l+1] - PcNAi[0];
  		else
  			alpha[l] = -PcNAo[l+1] + PcNAo[l-1] + PcNAi[l+1] - PcNAi[l-1];
  
  		alpha[l] *= 2 * pi;
  	}
  
  }
  
52a5fe9d   dmayerich   Added double supp...
193
194
  complex<double> integrateUs(double r, double lambda, complex<double> eta, 
  						   double cAngleI, double cAngleO, double oAngleI, double oAngleO, double M = 2*pi)
da3d4e0e   dmayerich   Initial commit.
195
196
197
198
199
200
201
202
203
204
205
206
207
  {
  	/*This function integrates the incident field of magnitude M in the far zone
  	in order to evaluate the field at the central pixel of a detector.
  	r = sphere radius
  	lambda = wavelength
  	eta = index of refraction
  	cNAi = condenser inner NA
  	cNAo = condenser outer NA
  	oNAi = objective inner NA
  	oNAo = objective outer NA
  	M = field magnitude*/
  
  	//compute the required number of orders
52a5fe9d   dmayerich   Added double supp...
208
209
  	double k = 2*pi/lambda;
  	int Nl = (int)ceil( k + 4 * exp(log(k*r)/3) + 3 );
da3d4e0e   dmayerich   Initial commit.
210
211
  
  	//compute the material coefficients B
52a5fe9d   dmayerich   Added double supp...
212
  	complex<double>* B = (complex<double>*)malloc(sizeof(complex<double>)*Nl);
da3d4e0e   dmayerich   Initial commit.
213
  	//compute the Legendre polynomials for the condenser and objective aperatures
52a5fe9d   dmayerich   Added double supp...
214
  	double* PcNAo = (double*)malloc(sizeof(double)*(Nl+1));
da3d4e0e   dmayerich   Initial commit.
215
  	Legendre(PcNAo, cos(cAngleO), Nl+1);
52a5fe9d   dmayerich   Added double supp...
216
  	double* PcNAi = (double*)malloc(sizeof(double)*(Nl+1));
da3d4e0e   dmayerich   Initial commit.
217
218
  	Legendre(PcNAi, cos(cAngleI), Nl+1);
  
52a5fe9d   dmayerich   Added double supp...
219
  	double* PoNAo = (double*)malloc(sizeof(double)*(Nl+1));
da3d4e0e   dmayerich   Initial commit.
220
  	Legendre(PoNAo, cos(oAngleO), Nl+1);
52a5fe9d   dmayerich   Added double supp...
221
  	double* PoNAi = (double*)malloc(sizeof(double)*(Nl+1));
da3d4e0e   dmayerich   Initial commit.
222
223
224
225
226
227
228
229
230
  	Legendre(PoNAi, cos(oAngleI), Nl+1);
  
  	//store the index of refraction;
  	complex<double> IR(eta.real(), eta.imag());
  	
  	//compute the scattering coefficients
  	computeB(B, r, IR, lambda, Nl);
  
  	//aperature terms for the condenser (alpha) and objective (beta)
52a5fe9d   dmayerich   Added double supp...
231
232
233
234
  	double alpha;
  	double beta;
  	double c;
  	complex<double> Us(0.0, 0.0);
da3d4e0e   dmayerich   Initial commit.
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
  
  	for(int l=0; l<Nl; l++)
  	{
  		//integration term
  		if(l == 0)
  		{
  			alpha = -PcNAo[l+1] + PcNAo[0] + PcNAi[l+1] - PcNAi[0];
  			beta = -PoNAo[l+1] + PoNAo[0] + PoNAi[l+1] - PoNAi[0];
  		}
  		else
  		{
  			alpha = -PcNAo[l+1] + PcNAo[l-1] + PcNAi[l+1] - PcNAi[l-1];
  			beta = -PoNAo[l+1] + PoNAo[l-1] + PoNAi[l+1] - PoNAi[l-1];
  		}
  		c = (2*pi)/(2.0 * l + 1.0);
  		Us += c * alpha * beta * B[l] * M;
  		
  			
  	}
  	free(PcNAo);
  	free(PcNAi);
  	free(PoNAo);
  	free(PoNAi);
  	free(B);
  
  	return Us;
  
  }
  
  void pointSpectrum()
  {
  	PD.StartTimer(SIMULATE_SPECTRUM);
  	//clear the previous spectrum
  	SimSpectrum.clear();
  
52a5fe9d   dmayerich   Added double supp...
270
271
  	double dNu = 2.0f;
  	double lambda;
da3d4e0e   dmayerich   Initial commit.
272
273
  	
  	//compute the angles based on NA
52a5fe9d   dmayerich   Added double supp...
274
275
276
277
  	double cAngleI = asin(cNAi);
  	double cAngleO = asin(cNAo);
  	double oAngleI = asin(oNAi);
  	double oAngleO = asin(oNAo);
da3d4e0e   dmayerich   Initial commit.
278
279
280
281
282
283
284
285
286
287
288
289
290
291
  
  	//implement a reflection-mode system if necessary
  	if(opticsMode == ReflectionOpticsType){
  		
  		//set the condenser to match the objective
  		cAngleI = oAngleI;
  		cAngleO = oAngleO;
  
  		//invert the objective
  		oAngleO = pi - cAngleI;
  		oAngleI = pi - cAngleO;
  	}
  
  	//integrate the incident field at the detector position
52a5fe9d   dmayerich   Added double supp...
292
293
  	complex<double> Ui = integrateUi(cAngleI, cAngleO, oAngleI, oAngleO, 2*pi);
  	double I0 = Ui.real() * Ui.real() + Ui.imag() * Ui.imag();
da3d4e0e   dmayerich   Initial commit.
294
295
296
297
  	I0 *= scaleI0;
  
  	
  
52a5fe9d   dmayerich   Added double supp...
298
  	//double I;
da3d4e0e   dmayerich   Initial commit.
299
  	SpecPair temp;
52a5fe9d   dmayerich   Added double supp...
300
301
302
  	double nu;
  	complex<double> eta;
  	complex<double> Us, U;
da3d4e0e   dmayerich   Initial commit.
303
  
52a5fe9d   dmayerich   Added double supp...
304
305
  	double vecLen = 0.0;
  	for(unsigned int i=0; i<EtaK.size(); i++)
da3d4e0e   dmayerich   Initial commit.
306
307
308
309
  	{
  		nu = EtaK[i].nu;
  		lambda = 10000.0f/nu;
  		if(applyMaterial)
52a5fe9d   dmayerich   Added double supp...
310
  			eta = complex<double>(EtaN[i].A, EtaK[i].A);
da3d4e0e   dmayerich   Initial commit.
311
  		else
52a5fe9d   dmayerich   Added double supp...
312
  			eta = complex<double>(baseIR, 0.0);
da3d4e0e   dmayerich   Initial commit.
313
314
315
316
317
  
  
  		//integrate the scattered field at the detector position
  		Us = integrateUs(radius, lambda, eta, cAngleI, cAngleO, oAngleI, oAngleO, 2*pi);
  		U = Us + Ui;
52a5fe9d   dmayerich   Added double supp...
318
  		double I = U.real() * U.real() + U.imag() * U.imag();
da3d4e0e   dmayerich   Initial commit.
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
  		
  		temp.nu = nu;
  
  		//set the spectrum value based on the current display type
  		if(dispSimType == AbsorbanceSpecType)
  			temp.A = -log10(I/I0);
  		else
  			temp.A = I;
  
  		if(dispNormalize)
  			vecLen += temp.A * temp.A;
  		
  		SimSpectrum.push_back(temp);		
  	}
  	vecLen = sqrt(vecLen);
  
  	if(dispNormalize)
52a5fe9d   dmayerich   Added double supp...
336
  		for(unsigned int i=0; i<SimSpectrum.size(); i++)
da3d4e0e   dmayerich   Initial commit.
337
338
339
340
341
  			SimSpectrum[i].A = (SimSpectrum[i].A / vecLen) * dispNormFactor;
  
  	PD.EndTimer(SIMULATE_SPECTRUM);
  }
  
52a5fe9d   dmayerich   Added double supp...
342
  void updateSpectrum(double* I, double I0, int n)
da3d4e0e   dmayerich   Initial commit.
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
  {
  	SimSpectrum.clear();
  	SpecPair temp;
  
  	//update the displayed spectrum based on the computed intensity I
  	for(int i=0; i<n; i++)
  	{
  		temp.nu = EtaK[i].nu;
  
  		//set the spectrum value based on the current display type
  		if(dispSimType == AbsorbanceSpecType)
  			temp.A = -log10(I[i]/I0);
  		else
  			temp.A = I[i];
  
  		SimSpectrum.push_back(temp);
  	}
  }
  
52a5fe9d   dmayerich   Added double supp...
362
  void computeCassegrainAngles(double& cAngleI, double& cAngleO, double& oAngleI, double& oAngleO)
da3d4e0e   dmayerich   Initial commit.
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
  {
  	//compute the angles based on NA
  	cAngleI = asin(cNAi);
  	cAngleO = asin(cNAo);
  	oAngleI = asin(oNAi);
  	oAngleO = asin(oNAo);
  
  	//implement a reflection-mode system if necessary
  	if(opticsMode == ReflectionOpticsType){
  		
  		//set the condenser to match the objective
  		cAngleI = oAngleI;
  		cAngleO = oAngleO;
  
  		//invert the objective
  		oAngleO = pi - cAngleI;
  		oAngleI = pi - cAngleO;
  	}
  
  
  }
  
  int computeNl()
  {
52a5fe9d   dmayerich   Added double supp...
387
388
389
390
  	double maxNu = EtaK.back().nu;
  	double maxLambda = 10000.0f/maxNu;
  	double k = 2*pi/maxLambda;
  	int Nl = (int)ceil( k + 4 * exp(log(k*radius)/3) + 3 );
da3d4e0e   dmayerich   Initial commit.
391
392
393
394
  
  	return Nl;
  }
  
52a5fe9d   dmayerich   Added double supp...
395
  void computeBArray(complex<double>* B, int Nl, int nLambda)
da3d4e0e   dmayerich   Initial commit.
396
  {
52a5fe9d   dmayerich   Added double supp...
397
398
399
  	double nu;
  	complex<double> eta;
  	double* Lambda = (double*)malloc(sizeof(double) * nLambda);
da3d4e0e   dmayerich   Initial commit.
400
401
  
  	//for each wavenumber nu
52a5fe9d   dmayerich   Added double supp...
402
  	for(unsigned int i=0; i<EtaK.size(); i++)
da3d4e0e   dmayerich   Initial commit.
403
404
405
406
407
  	{
  		//compute information based on wavelength and material
  		nu = EtaK[i].nu;
  		Lambda[i] = 10000.0f/nu;
  		if(applyMaterial)
52a5fe9d   dmayerich   Added double supp...
408
  			eta = complex<double>(EtaN[i].A, EtaK[i].A);
da3d4e0e   dmayerich   Initial commit.
409
  		else
52a5fe9d   dmayerich   Added double supp...
410
  			eta = complex<double>(baseIR, 0.0);
da3d4e0e   dmayerich   Initial commit.
411
412
413
414
415
416
417
418
419
  
  		//allocate memory for the scattering coefficients
  		//complex<float>* B = (complex<float>*)malloc(sizeof(complex<float>)*Nl);		
  
  		complex<double> IR(eta.real(), eta.imag());
  		computeB(&B[i * Nl], radius, IR, Lambda[i], Nl);
  	}
  }
  
52a5fe9d   dmayerich   Added double supp...
420
  void computeOpticalParameters(double& cAngleI, double& cAngleO, double& oAngleI, double& oAngleO, double& I0, double* alpha, int Nl)
da3d4e0e   dmayerich   Initial commit.
421
422
423
424
425
  {
  	computeCassegrainAngles(cAngleI, cAngleO, oAngleI, oAngleO);	
  
  	//evaluate the incident field intensity
  	I0 = 0.0;
52a5fe9d   dmayerich   Added double supp...
426
  	complex<double> Ui;
da3d4e0e   dmayerich   Initial commit.
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
  
  	Ui = integrateUi(cAngleI, cAngleO, oAngleI, oAngleO, 2*pi);
  	I0 = Ui.real()*2*pi;
  
  	//compute alpha (condenser integral)
  	computeCondenserAlpha(alpha, Nl, cAngleI, cAngleO);
  }
  
  void gpuDetectorSpectrum(int numSamples)
  {
  	//integrate across the objective aperature and calculate the resulting intensity on a detector
  	PD.StartTimer(SIMULATE_SPECTRUM);
  	//clear the previous spectrum
  	SimSpectrum.clear();	
  
  	//compute Nl (maximum order of the spectrum)
  	int Nl = computeNl();
  
52a5fe9d   dmayerich   Added double supp...
445
446
  	double* alpha = (double*)malloc(sizeof(double)*(Nl + 1));
  	double cAngleI, cAngleO, oAngleI, oAngleO, I0;
da3d4e0e   dmayerich   Initial commit.
447
448
449
450
451
452
  	computeOpticalParameters(cAngleI, cAngleO, oAngleI, oAngleO, I0, alpha, Nl);
  
  	//allocate space for a list of wavelengths
  	int nLambda = EtaK.size();
  	
  	//allocate space for the 2D array (Nl x nu) of scattering coefficients
52a5fe9d   dmayerich   Added double supp...
453
  	complex<double>* B = (complex<double>*)malloc(sizeof(complex<double>) * Nl * nLambda);
da3d4e0e   dmayerich   Initial commit.
454
455
456
457
  	computeBArray(B, Nl, nLambda);
  	
  
  	//allocate temporary space for the spectrum
52a5fe9d   dmayerich   Added double supp...
458
  	double* I = (double*)malloc(sizeof(double) * EtaK.size());
da3d4e0e   dmayerich   Initial commit.
459
460
461
  
  	//compute the spectrum on the GPU
  	PD.StartTimer(SIMULATE_GPU);
52a5fe9d   dmayerich   Added double supp...
462
  	cudaComputeSpectrum(I, (double*)B, alpha, Nl, nLambda, oAngleI, oAngleO, cAngleI, cAngleO, numSamples);
da3d4e0e   dmayerich   Initial commit.
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
  	PD.EndTimer(SIMULATE_GPU);
  
  	updateSpectrum(I, I0, nLambda);
  
  	PD.EndTimer(SIMULATE_SPECTRUM);
  
  }
  
  void SimulateSpectrum()
  {
  	if(pointDetector)
  		pointSpectrum();
  	else
  		gpuDetectorSpectrum(objectiveSamples);
  		//detectorSpectrum(objectiveSamples);
  }
  
52a5fe9d   dmayerich   Added double supp...
480
  double absorbanceDistortion(){
da3d4e0e   dmayerich   Initial commit.
481
482
  
  	//compute the mean of the spectrum
52a5fe9d   dmayerich   Added double supp...
483
484
  	double sumSim = 0.0;
  	for(unsigned int i=0; i<SimSpectrum.size(); i++)
da3d4e0e   dmayerich   Initial commit.
485
486
487
  	{
  		sumSim += SimSpectrum[i].A;
  	}
52a5fe9d   dmayerich   Added double supp...
488
  	double meanSim = sumSim/SimSpectrum.size();
da3d4e0e   dmayerich   Initial commit.
489
490
  
  	//compute the distortion (MSE from the mean)
52a5fe9d   dmayerich   Added double supp...
491
492
  	double sumSE = 0.0;
  	for(unsigned int i=0; i<SimSpectrum.size(); i++)
da3d4e0e   dmayerich   Initial commit.
493
494
495
  	{
  		sumSE += pow(SimSpectrum[i].A - meanSim, 2);
  	}
52a5fe9d   dmayerich   Added double supp...
496
  	double MSE = sumSE / SimSpectrum.size();
da3d4e0e   dmayerich   Initial commit.
497
498
499
500
  
  	return MSE;
  }
  
52a5fe9d   dmayerich   Added double supp...
501
  double intensityDistortion(){
da3d4e0e   dmayerich   Initial commit.
502
503
  
  	//compute the magnitude of the spectrum
52a5fe9d   dmayerich   Added double supp...
504
505
  	double sumSim = 0.0;
  	for(unsigned int i=0; i<SimSpectrum.size(); i++)
da3d4e0e   dmayerich   Initial commit.
506
507
508
  	{
  		sumSim += SimSpectrum[i].A * SimSpectrum[i].A;
  	}
52a5fe9d   dmayerich   Added double supp...
509
  	double magSim = sqrt(sumSim);
da3d4e0e   dmayerich   Initial commit.
510
511
  
  	//compute the distortion (MSE from the mean)
52a5fe9d   dmayerich   Added double supp...
512
513
  	double sumSE = 0.0;
  	for(unsigned int i=0; i<SimSpectrum.size(); i++)
da3d4e0e   dmayerich   Initial commit.
514
515
516
  	{
  		sumSE += (SimSpectrum[i].A/magSim) * (1.0/SimSpectrum.size());
  	}
52a5fe9d   dmayerich   Added double supp...
517
  	double MSE = sumSE;
da3d4e0e   dmayerich   Initial commit.
518
519
520
521
522
523
524
525
  
  	return MSE;
  }
  
  void MinimizeDistortion(){
  	ofstream outFile("distortion.txt");
  
  	//set the parameters for the distortion simulation
52a5fe9d   dmayerich   Added double supp...
526
  	double step = 0.001;
da3d4e0e   dmayerich   Initial commit.
527
528
529
530
531
532
533
534
  
  	oNAi = 0.2;
  	oNAo = 0.5;
  
  	//compute the optical parameters
  	//compute Nl (maximum order of the spectrum)
  	int Nl = computeNl();
  
52a5fe9d   dmayerich   Added double supp...
535
536
  	double* alpha = (double*)malloc(sizeof(double)*(Nl + 1));
  	double cAngleI, cAngleO, oAngleI, oAngleO, I0;
da3d4e0e   dmayerich   Initial commit.
537
538
539
540
541
  	
  	//allocate space for a list of wavelengths
  	int nLambda = EtaK.size();
  
  	//allocate temporary space for the spectrum
52a5fe9d   dmayerich   Added double supp...
542
  	double* I = (double*)malloc(sizeof(double) * EtaK.size());
da3d4e0e   dmayerich   Initial commit.
543
544
545
  
  	//calculate the material parameters
  	//allocate space for the 2D array (Nl x nu) of scattering coefficients
52a5fe9d   dmayerich   Added double supp...
546
  	complex<double>* B = (complex<double>*)malloc(sizeof(complex<double>) * Nl * nLambda);
da3d4e0e   dmayerich   Initial commit.
547
548
549
550
  	computeBArray(B, Nl, nLambda);
  
  
  
52a5fe9d   dmayerich   Added double supp...
551
552
553
  	double D;
  	double e = 0.001;
  	for(double i=0.0; i<=oNAo-step; i+=step)
da3d4e0e   dmayerich   Initial commit.
554
555
  	{
  		
52a5fe9d   dmayerich   Added double supp...
556
  		for(double o=oNAi+step; o<=1.0; o+=step)
da3d4e0e   dmayerich   Initial commit.
557
558
559
560
561
562
563
564
565
566
567
  		{
  			
  			
  			//set the current optical parameters
  			cNAi = i;
  			cNAo = o;
  
  			//compute the optical parameters
  			computeOpticalParameters(cAngleI, cAngleO, oAngleI, oAngleO, I0, alpha, Nl);
  
  			//simulate the spectrum
52a5fe9d   dmayerich   Added double supp...
568
  			cudaComputeSpectrum(I, (double*)B, alpha, Nl, nLambda, oAngleI, oAngleO, cAngleI, cAngleO, objectiveSamples);
da3d4e0e   dmayerich   Initial commit.
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
  			updateSpectrum(I, I0, nLambda);
  
  			if(dispSimType == AbsorbanceSpecType)
  			{
  				if(i + e >= o || i + e >= oNAo || oNAi + e >= o || oNAi + e >= oNAo)
  					D = 0.0;
  				else
  					D = absorbanceDistortion();
  			}
  			else
  			{
  				if(i >= o || oNAi >= oNAo)
  					D=0;
  				else
  					D = intensityDistortion();
  			}
  			outFile<<D<<"       ";
  		}
  		outFile<<endl;
  		cout<<i<<endl;
  	}
  	outFile.close();
  }