source: src/main/java/agents/anac/y2015/agentBuyogV2/flanagan/optics/Reflectivity.java

Last change on this file was 127, checked in by Wouter Pasman, 6 years ago

#41 ROLL BACK of rev.126 . So this version is equal to rev. 125

File size: 142.8 KB
Line 
1/*
2* Reflectivity Class
3*
4* Methods for calculating the reflection of light from
5* the surface of a multilayer of dielectic and/or metal layers
6* and of fitting experimental data to a reflectivity, transmissivity
7* or evanescent field strength scan against angle or wavelength
8*
9* Methods for fitting data to a reflectivty, transmissivitty or evanescent field
10* scan over a range of incident angles at a single wavelength
11*
12* Author: Dr Michael Thomas Flanagan.
13*
14* Created: February/March/April 2006
15* Developed from earlier C++ and Fortran programs
16* Revised 26 April 2006, 5-7 July 2008
17*
18* DOCUMENTATION:
19* See Michael Thomas Flanagan's Java library on-line web page:
20* http://www.ee.ucl.ac.uk/~mflanaga/java/Refflectivity.html
21* http://www.ee.ucl.ac.uk/~mflanaga/java/
22*
23* Copyright (c) March 2006 Michael Thomas Flanagan
24*
25* PERMISSION TO COPY:
26* Permission to use, copy and modify this software and its documentation for
27* NON-COMMERCIAL purposes is granted, without fee, provided that an acknowledgement
28* to the author, Michael Thomas Flanagan at www.ee.ucl.ac.uk/~mflanaga, appears in all copies.
29*
30* Dr Michael Thomas Flanagan makes no representations about the suitability
31* or fitness of the software for any or for a particular purpose.
32* Michael Thomas Flanagan shall not be liable for any damages suffered
33* as a result of using, modifying or distributing this software or its derivatives.
34*
35***************************************************************************************/
36
37package agents.anac.y2015.agentBuyogV2.flanagan.optics;
38
39import java.lang.reflect.Array;
40import java.util.ArrayList;
41
42import agents.anac.y2015.agentBuyogV2.flanagan.analysis.Regression;
43import agents.anac.y2015.agentBuyogV2.flanagan.analysis.RegressionFunction;
44import agents.anac.y2015.agentBuyogV2.flanagan.complex.Complex;
45import agents.anac.y2015.agentBuyogV2.flanagan.complex.ComplexMatrix;
46import agents.anac.y2015.agentBuyogV2.flanagan.math.Conv;
47import agents.anac.y2015.agentBuyogV2.flanagan.math.Fmath;
48import agents.anac.y2015.agentBuyogV2.flanagan.plot.PlotGraph;
49
50public class Reflectivity {
51
52 // CLASS VARIABLES
53
54 private int numberOfLayers = 0; // number of layers including the
55 // semi-infinite layer at both outer faces
56 private int numberOfInterfaces = 0; // number of interlayer interfaces, i.e.
57 // number of layers minus one
58
59 private Complex[][] refractiveIndices = null; // refractive indices of the
60 // layers at all wavelengths
61 // (number of wavelength,
62 // number of layers)
63 private Complex[] meanRefractiveIndices = null; // mean refractive indices
64 // of each layer
65 private boolean refractSet = false; // = true when refractive indices
66 // entered
67 private boolean[] refractLayerSet = null; // = true for layer i when
68 // refractive indices entered
69 // for layer i
70 private boolean meanRefractUsed = false; // = true when mean refractive
71 // indices used
72
73 private Complex[][] relativeMagneticPermeabilities = null; // relative
74 // magnetic
75 // permeabilities
76 // of the layers
77 // default
78 // values = 1.0
79 private Complex[] meanRelativeMagneticPermeabilities = null;// mean relative
80 // magnetic
81 // permeabilities
82 // of the layers
83 private boolean magneticSet = false; // = true when relative magnetic
84 // permeabilities entered
85 private boolean meanMagneticUsed = false; // = true when mean relative
86 // magnetic permeabilities used
87
88 private double[][] absorptionCoefficients = null; // absorption coefficents
89 // of the layers at all
90 // wavelengths
91 // default values = 0.0;
92 private boolean absorbSet = false; // = true when absorbtivity or extinction
93 // coefficients entered
94
95 private double[] thicknesses = null; // thicknesses (in metres) of the
96 // layers
97 private double[] distances = null; // cumulative thicknesses (in metres)
98 private boolean thickSet = false; // = true when thicknesses entered
99 private boolean[] thickLayerSet = null; // = true for layer i when
100 // thicknesses entered for layer i
101
102 private int numberOfWavelengths = 0; // number of wavelengths in wavelength
103 // scan
104 private double[] wavelengths = null; // wavelengths (in metres) in scan
105 private double[] frequencies = null; // frequencies (in Hz) in scan
106 private double[] omega = null; // radial frequencies (in radians) in scan
107 private int[] origWavelIndices = null; // indices of the wavelengths as
108 // entered before sort into lowest
109 // to highest
110 private boolean wavelSet = false; // = true when wavelengths entered
111 private boolean freqSet = false; // = true when frequencies entered
112 private boolean wavelNumberSet = false; // = true when number of wavelengths
113 // set
114
115 private double[] incidentAngleDeg = null; // incident angles measured from
116 // the normal in degrees
117 private double[] incidentAngleRad = null; // incident angles measured from
118 // the normal in radians
119 private int[] incidentAngleIndices = null; // indices of original incident
120 // angles after sorting into
121 // ascending order
122 private int numberOfIncidentAngles = 0; // number of incident angles in
123 // angular scan
124 private boolean incidentAngleSet = false; // = true when the incident angles
125 // have been entered
126
127 private String mode = null; // polarisation mode: TE, TM, unpolarised or
128 // mixed
129 private double eVectorAngleDeg = 0.0D; // angle between the electric vector
130 // of the incident light and
131 // the plane normal to the
132 // reflecting surfac in degrees
133 private double eVectorAngleRad = 0.0D; // angle between the electric vector
134 // of the incident light and
135 // the plane normal to the
136 // reflecting surfac in radians
137 private double teFraction = 0.0D; // fraction of light in the TE mode
138 private double tmFraction = 0.0D; // fraction of light in the TM mode
139 private boolean modeSet = false; // = true when mode set
140
141 private Complex[][][] koVector = null; // ko vector [wavelength] [incident
142 // angle] [layer]
143 private Complex[][][] kVector = null; // k vector [wavelength] [incident
144 // angle] [layer]
145 private Complex[][][] kxVector = null; // kx vector [wavelength] [incident
146 // angle] [layer]
147 private Complex[][][] kzVector = null; // kz vector [wavelength] [incident
148 // angle] [layer]
149
150 private double[][] reflectivities = null; // reflectivities [wavelength]
151 // [incident angle]
152 private double[][] transmissivities = null; // transmissivities [wavelength]
153 // [incident angle]
154 private double[][] powerLosses = null; // power loss on transmission
155 // relative to an input power of 1mW
156 // over 1 sq. metre [wavelength]
157 // [incident angle]
158 private Complex[][] reflectCoeffTE = null; // TE reflection coefficient
159 // [wavelength] [incident angle]
160 private Complex[][] reflectCoeffTM = null; // TM reflection coefficient
161 // [wavelength] [incident angle]
162 private Complex[][] transmitCoeffTE = null; // TE transmission coefficient
163 // [wavelength] [incident angle]
164 private Complex[][] transmitCoeffTM = null; // TM transmissiom coefficient
165 // [wavelength] [incident angle]
166
167 private double[][] reflectPhaseShiftRadTE = null; // TE reflection phase
168 // shift (radians)
169 // [wavelength]
170 // [incident angle]
171 private double[][] reflectPhaseShiftRadTM = null; // TM reflection phase
172 // shift (radians)
173 // [wavelength]
174 // [incident angle]
175 private double[][] transmitPhaseShiftRadTE = null; // TE transmission phase
176 // shift (radians)
177 // [wavelength]
178 // [incident angle]
179 private double[][] transmitPhaseShiftRadTM = null; // TM transmissiom phase
180 // shift (radians)
181 // [wavelength]
182 // [incident angle]
183 private double[][] reflectPhaseShiftDegTE = null; // TE reflection phase
184 // shift (degrees)
185 // [wavelength]
186 // [incident angle]
187 private double[][] reflectPhaseShiftDegTM = null; // TM reflection phase
188 // shift (degrees)
189 // [wavelength]
190 // [incident angle]
191 private double[][] transmitPhaseShiftDegTE = null; // TE transmission phase
192 // shift (degrees)
193 // [wavelength]
194 // [incident angle]
195 private double[][] transmitPhaseShiftDegTM = null; // TM transmissiom phase
196 // shift (degrees)
197 // [wavelength]
198 // [incident angle]
199
200 private double[][] evanescentFields = null; // integrated evanescent fields
201 // [wavelength] [incident angle]
202 private double fieldDistance = Double.POSITIVE_INFINITY; // distance into
203 // evanescent
204 // field over
205 // which
206 // intensity is
207 // integrated
208 private boolean fieldIntensityCalc = false; // = true when field intensity
209 // calculated for non-infinite
210 // field distance
211 private double[][] penetrationDepths = null; // Evanescent field penetration
212 // depth [wavelength]
213 // [incident angle]
214 private double[][] transmitAnglesRad = null; // transmitted angles in
215 // radians [wavelength]
216 // [incident angle]
217 private double[][] transmitAnglesDeg = null; // transmitted angles in
218 // degrees [wavelength]
219 // [incident angle]
220
221 private boolean singleReflectCalculated = false; // = true when only a
222 // single angular
223 // relectivity has been
224 // calculated
225 private boolean angularReflectCalculated = false; // = true when an angular
226 // relectivity scan has
227 // been calculated
228 private boolean wavelengthReflectCalculated = false; // = true when an
229 // wavelength
230 // relectivity scan
231 // has been
232 // calculated
233 private boolean wavelengthAndAngularReflectCalculated = false; // = true
234 // when
235 // angular
236 // for each
237 // wavelength
238 // relectivity
239 // scan has
240 // been
241 // calculated
242
243 private double mu0overEps0 = Fmath.MU_0 / Fmath.EPSILON_0; // permeability
244 // of free space
245 // over
246 // permittivity
247 // of free space
248 private double impedance = Math.sqrt(mu0overEps0); // characteristic
249 // impedance of free
250 // space
251
252 private int wavelengthAxisOption = 1; // = 1 when wavelength/frequency
253 // x-axis in plotting methods =
254 // wavelength
255 // = 2 when wavelength/frequency
256 // x-axis in plotting methods =
257 // frequency, Hz
258 // = 3 when wavelength/frequency
259 // x-axis in plotting methods =
260 // radians
261
262 private double[] experimentalData = null; // experimental data [incident
263 // angle]
264 private double[] experimentalWeights = null; // error in each experimental
265 // point [incident angle]
266 private double[] calculatedData = null; // calculated data [incident angle]
267
268 private int numberOfDataPoints = 0; // number of experimental data points
269 private boolean experimentalDataSet = false; // = true when experimental
270 // data entered
271 private boolean weightingOption = false; // = true if experimental
272 // weightings (other than unity)
273 // entered
274
275 private int numberOfEstimatedParameters = 0; // number of parameters to be
276 // estimated in non-linear
277 // regression method
278 private int[] thicknessEstimateIndices = null; // indices of the thicknesses
279 // to be estimated by
280 // non-linear regression
281 private int[] refractIndexRealEstimateIndices = null; // indices of the
282 // Real[refractive
283 // indices] to be
284 // estimated by
285 // non-linear
286 // regression
287 private int[] refractIndexImagEstimateIndices = null; // indices of the
288 // Imag[refractive
289 // indices] to be
290 // estimated by
291 // non-linear
292 // regression
293 private int[] absorptionCoeffEstimateIndices = null; // indices of the
294 // absorption
295 // coefficients to
296 // be estimated by
297 // non-linear
298 // regression
299 private int[] magneticPermRealEstimateIndices = null; // indices of the
300 // Real[relative
301 // magnetic
302 // permeability] to
303 // be estimated by
304 // non-linear
305 // regression
306 private int[] magneticPermImagEstimateIndices = null; // indices of the
307 // Imag[relative
308 // magnetic
309 // permeability] to
310 // be estimated by
311 // non-linear
312 // regression
313
314 private boolean refractIndexImagEstimateSet = false; // = true when indices
315 // of the
316 // Imag[refractive
317 // indices] set
318 private boolean absorptionCoeffEstimateSet = false; // = true when indices
319 // of the absorption
320 // coefficients set
321
322 private int thicknessEstimateNumber = 0; // number of the thicknesses to be
323 // estimated by non-linear
324 // regression
325 private int refractIndexRealEstimateNumber = 0; // number of the
326 // Real[refractive indices]
327 // to be estimated by
328 // non-linear regression
329 private int refractIndexImagEstimateNumber = 0; // number of the
330 // Imag[refractive indices]
331 // to be estimated by
332 // non-linear regression
333 private int absorptionCoeffEstimateNumber = 0; // number of the absorption
334 // coefficients to be
335 // estimated by non-linear
336 // regression
337 private int magneticPermRealEstimateNumber = 0; // number of the
338 // Real[relative magnetic
339 // permeabilities] to be
340 // estimated by non-linear
341 // regression
342 private int magneticPermImagEstimateNumber = 0; // number of the
343 // Imag[relative magnetic
344 // permeabilities] to be
345 // estimated by non-linear
346 // regression
347
348 private double fieldScalingFactor = 0.0D; // scaling factor between
349 // calculated and experimental
350 // field values
351
352 public int regressionOption = 0; // Regression option
353 // = 1; reflectivity versus angle
354 // = 2; transmissivity versus angle
355 // = 3; evanescent field versus angle
356 public int degreesOfFreedom = 0; // degrees of freedom (non-linear
357 // regression method)
358
359 // CONSTRUCTOR
360
361 public Reflectivity(int n) {
362 this.numberOfLayers = n;
363 this.numberOfInterfaces = n - 1;
364 if (n < 2)
365 throw new IllegalArgumentException("There must be at least two layers, i.e. at least one interface");
366
367 this.meanRelativeMagneticPermeabilities = Complex.oneDarray(this.numberOfLayers, 1.0D, 0.0D);
368
369 this.meanRefractiveIndices = Complex.oneDarray(this.numberOfLayers);
370 this.refractLayerSet = new boolean[this.numberOfLayers];
371 for (int i = 0; i < this.numberOfLayers; i++)
372 this.refractLayerSet[i] = false;
373
374 this.thicknesses = new double[this.numberOfLayers];
375 this.thicknesses[0] = Double.NEGATIVE_INFINITY;
376 this.thicknesses[this.numberOfLayers - 1] = Double.POSITIVE_INFINITY;
377 this.thickLayerSet = new boolean[this.numberOfLayers];
378 this.thickLayerSet[0] = true;
379 for (int i = 1; i < this.numberOfLayers - 2; i++)
380 this.thickLayerSet[i] = false;
381 this.thickLayerSet[this.numberOfLayers - 1] = true;
382
383 this.distances = new double[this.numberOfInterfaces];
384 }
385
386 // POLARISATION MODE
387
388 // Enter polarisation mode - TE or TM or unpolarised
389 public void setMode(String mode) {
390 if (mode.equalsIgnoreCase("TE") || mode.equalsIgnoreCase("transverse electric")) {
391 this.mode = "TE";
392 this.teFraction = 1.0D;
393 this.tmFraction = 0.0D;
394 this.eVectorAngleDeg = 0.0D;
395 this.eVectorAngleRad = 0.0D;
396 } else {
397 if (mode.equalsIgnoreCase("TM") || mode.equalsIgnoreCase("transverse magnetic")) {
398 this.mode = "TM";
399 this.teFraction = 0.0D;
400 this.tmFraction = 1.0D;
401 this.eVectorAngleDeg = 90.0D;
402 this.eVectorAngleRad = Math.PI / 2.0D;
403 } else {
404 if (mode.equalsIgnoreCase("unpolarised") || mode.equalsIgnoreCase("unpolarized")
405 || mode.equalsIgnoreCase("none")) {
406 this.mode = "unpolarised";
407 this.teFraction = 0.5D;
408 this.tmFraction = 0.5D;
409 this.eVectorAngleDeg = 45.0D;
410 this.eVectorAngleRad = Math.PI / 4.0D;
411 } else {
412 throw new IllegalArgumentException("mode must be TE, TM or unpolarised; it cannot be " + mode);
413 }
414 }
415 }
416 this.modeSet = true;
417 }
418
419 // Enter angle between incident light electric vector and the plane normal
420 // to the reflecting plane in degrees
421 public void setMode(double modeAngle) {
422 this.mode = "mixed";
423 this.eVectorAngleDeg = modeAngle;
424 this.eVectorAngleRad = Math.toRadians(modeAngle);
425 this.teFraction = Math.sin(this.eVectorAngleRad);
426 this.teFraction *= this.teFraction;
427 this.tmFraction = 1.0D - this.teFraction;
428 this.modeSet = true;
429 }
430
431 // Return the fractional TE component
432 public double fractionInTEmode() {
433 return this.teFraction;
434 }
435
436 // Return the fractional TM component
437 public double fractionInTMmode() {
438 return this.tmFraction;
439 }
440
441 // INCIDENT ANGLES
442
443 // Enter a single incident angle (degrees)
444 public void setIncidentAngle(double incidentAngle) {
445 double[] incident = { incidentAngle };
446 this.setIncidentAngle(incident);
447 }
448
449 // Enter an array of incident angles (degrees)
450 public void setIncidentAngle(double[] incidentAngle) {
451 this.numberOfIncidentAngles = incidentAngle.length;
452 this.incidentAngleIndices = new int[this.numberOfIncidentAngles];
453 this.incidentAngleDeg = new double[this.numberOfIncidentAngles];
454 Fmath.selectionSort(incidentAngle, this.incidentAngleDeg, this.incidentAngleIndices);
455 if (this.experimentalDataSet) {
456 if (this.numberOfDataPoints != this.numberOfIncidentAngles)
457 throw new IllegalArgumentException("Number of experimental reflectivities " + this.numberOfDataPoints
458 + " does not equal the number of incident angles " + this.numberOfIncidentAngles);
459 double[] temp = Conv.copy(this.experimentalData);
460 for (int i = 0; i < this.numberOfIncidentAngles; i++)
461 this.experimentalData[i] = temp[this.incidentAngleIndices[i]];
462 }
463 this.incidentAngleRad = new double[this.numberOfIncidentAngles];
464 for (int i = 0; i < this.numberOfIncidentAngles; i++)
465 this.incidentAngleRad[i] = Math.toRadians(this.incidentAngleDeg[i]);
466 this.incidentAngleSet = true;
467 }
468
469 // Enter a range of nAngles incident angles [degrees] ranging, in equal
470 // increments from angleLow to angleHigh
471 public void setIncidentAngle(double angleLow, double angleHigh, int nAngles) {
472 this.numberOfIncidentAngles = nAngles;
473 double increment = (angleHigh - angleLow) / (nAngles - 1);
474 double[] incidentAngles = new double[nAngles];
475 incidentAngles[0] = angleLow;
476 for (int i = 1; i < nAngles - 1; i++)
477 incidentAngles[i] = incidentAngles[i - 1] + increment;
478 incidentAngles[nAngles - 1] = angleHigh;
479 this.setIncidentAngle(incidentAngles);
480 }
481
482 // Return the incident angles (in degrees)
483 public double[] getIncidentAngles() {
484 return this.incidentAngleDeg;
485 }
486
487 // THICKNESSES
488
489 // Enter layer thicknesses (metres) excluding outer semi-infinite layers
490 public void setThicknesses(double[] thick) {
491 int n = thick.length;
492 if (n != this.numberOfLayers - 2)
493 throw new IllegalArgumentException("Number of thicknesses, " + n
494 + ", does not match the number of layers minus the outer two semi-finite layers, "
495 + (this.numberOfLayers - 2));
496 for (int i = 1; i < this.numberOfLayers - 1; i++)
497 this.thicknesses[i] = thick[i - 1];
498
499 // Calculate distances
500 this.distances[0] = 0.0D;
501 for (int i = 1; i < this.numberOfInterfaces; i++)
502 this.distances[i] = this.distances[i - 1] + this.thicknesses[i];
503
504 for (int i = 1; i < this.numberOfLayers - 2; i++)
505 this.thickLayerSet[i] = true;
506 this.thickSet = true;
507 }
508
509 // Enter layer thicknesses (metres) for individual layer
510 public void setThicknesses(double thickness, int layerNumber) {
511 if (layerNumber < 1 || layerNumber > this.numberOfLayers)
512 throw new IllegalArgumentException(
513 "Layer number, " + layerNumber + ", must be in the range 1 to " + this.numberOfLayers);
514 this.thicknesses[layerNumber - 1] = thickness;
515
516 // Recalculate distances
517 this.distances[0] = 0.0D;
518 for (int i = 1; i < this.numberOfInterfaces; i++)
519 this.distances[i] = this.distances[i - 1] + this.thicknesses[i];
520
521 this.thickLayerSet[layerNumber - 1] = true;
522 int check = 0;
523 for (int i = 0; i < this.numberOfLayers - i; i++)
524 if (this.thickLayerSet[i])
525 check++;
526 if (check == this.numberOfLayers)
527 this.thickSet = true;
528 }
529
530 // Return the layer thicknesses
531 public double[] getThicknesses() {
532 return this.thicknesses;
533 }
534
535 // WAVELENGTH AND FREQUENCIES
536
537 // Enter wavelengths (metres)
538 public void setWavelength(double[] wavelengths) {
539 // set wavelengths
540 int n = wavelengths.length;
541 if (this.wavelNumberSet) {
542 if (n != this.numberOfWavelengths)
543 throw new IllegalArgumentException("The number of wavelengths entered, " + n
544 + ", does not equal that previously set," + this.numberOfWavelengths);
545 }
546 this.numberOfWavelengths = n;
547 this.wavelengths = wavelengths;
548 this.wavelSet = true;
549
550 // set refractive indices array dimensions
551 if (!refractSet)
552 this.refractiveIndices = Complex.twoDarray(this.numberOfWavelengths, this.numberOfLayers);
553
554 // fill out mean refractive indices if necessary
555 if (!this.wavelNumberSet) {
556 // Fill out refractive index arrays if mean values have been entered
557 if (this.meanRefractUsed) {
558 for (int i = 0; i < this.numberOfLayers; i++) {
559 for (int j = 0; j < this.numberOfWavelengths; j++) {
560 this.refractiveIndices[j][i] = this.meanRefractiveIndices[i];
561 }
562 }
563 for (int i = 0; i < this.numberOfLayers; i++)
564 this.refractLayerSet[i] = true;
565 this.refractSet = true;
566 }
567
568 // Calculate imaginary refractive indices arrays if absorption
569 // coefficients have been entered
570 // or otherwise set all absorption coefficients to zero
571 if (this.absorptionCoefficients != null) {
572 for (int i = 0; i < this.numberOfLayers; i++) {
573 for (int j = 0; j < this.numberOfWavelengths; j++) {
574 if (this.refractiveIndices[i][j].getImag() == 0.0D)
575 this.refractiveIndices[j][i]
576 .setImag(absorptionCoefficients[j][i] * this.wavelengths[j] / (4.0D * Math.PI));
577 }
578 }
579 } else {
580 this.absorptionCoefficients = new double[this.numberOfWavelengths][this.numberOfLayers];
581 }
582
583 // Fill out relative magnetic permeability arrays if empty
584 this.relativeMagneticPermeabilities = Complex.twoDarray(this.numberOfWavelengths, this.numberOfLayers);
585 if (this.meanMagneticUsed) {
586 // if mean values have been entered
587 for (int i = 0; i < this.numberOfLayers; i++) {
588 for (int j = 0; j < this.numberOfWavelengths; j++) {
589 this.relativeMagneticPermeabilities[j][i] = this.meanRelativeMagneticPermeabilities[i];
590 }
591 }
592 this.magneticSet = true;
593 } else {
594 // if no values have been entered set all to unity
595 for (int i = 0; i < this.numberOfLayers; i++) {
596 for (int j = 0; j < this.numberOfWavelengths; j++) {
597 this.relativeMagneticPermeabilities[j][i] = Complex.plusOne();
598 }
599 }
600 }
601 }
602
603 // calculate frequencies
604 if (!freqSet) {
605 this.frequencies = new double[this.numberOfWavelengths];
606 for (int i = 0; i < this.numberOfWavelengths; i++)
607 this.frequencies[this.numberOfWavelengths - 1 - i] = Fmath.C_LIGHT / wavelengths[i];
608 }
609
610 // calculate radial frequencies
611 this.omega = new double[this.numberOfWavelengths];
612 for (int i = 0; i < this.numberOfWavelengths; i++)
613 this.omega[i] = 2.0D * Math.PI * frequencies[i];
614
615 this.wavelNumberSet = true;
616 }
617
618 // Enter frequencies (Hz)
619 public void setFrequency(double[] frequency) {
620 // set frequencies
621 int n = frequency.length;
622 if (this.wavelNumberSet) {
623 if (n != this.numberOfWavelengths)
624 throw new IllegalArgumentException("The number of frequencies entered, " + n
625 + ", does not equal that previously set," + this.numberOfWavelengths);
626 }
627 this.frequencies = frequency;
628 this.freqSet = true;
629 this.wavelengthAxisOption = 2;
630
631 // set wavelengths
632 double[] wavelength = new double[n];
633 for (int i = 0; i < n; i++)
634 wavelength[i] = Fmath.C_LIGHT / frequencies[n - 1 - i];
635 this.setWavelength(wavelength);
636 }
637
638 // Enter a range of nLambda wavelengths [metres] ranging, in equal
639 // increments from lambdaLow to lambdaHigh
640 public void setWavelength(double lambdaLow, double lambdaHigh, int nLambda) {
641 double increment = (lambdaHigh - lambdaLow) / (nLambda - 1);
642 double[] wavelength = new double[nLambda];
643 wavelength[0] = lambdaLow;
644 for (int i = 1; i < nLambda - 1; i++)
645 wavelength[i] = wavelength[i - 1] + increment;
646 wavelength[nLambda - 1] = lambdaHigh;
647 this.setWavelength(wavelength);
648 }
649
650 // Enter a range of nFreq frequencies [Hz] ranging, in equal increments from
651 // freqLow to freqHigh
652 public void setFrequency(double freqLow, double freqHigh, int nFreq) {
653 double increment = (freqHigh - freqLow) / (nFreq - 1);
654 double[] frequency = new double[nFreq];
655 frequency[0] = freqLow;
656 for (int i = 1; i < nFreq - 1; i++)
657 frequency[i] = frequency[i - 1] + increment;
658 frequency[nFreq - 1] = freqHigh;
659 this.setFrequency(frequency);
660 }
661
662 // Enter a single wavelength [metres]
663 public void setWavelength(double wavelength) {
664 double[] wavelengths = { wavelength };
665 this.setWavelength(wavelengths);
666 }
667
668 // Enter a single frequency [Hz]
669 public void setFrequency(double frequency) {
670 double[] frequencies = { frequency };
671 this.setFrequency(frequencies);
672 }
673
674 // Return the wavelengths
675 public double[] getWavelengths() {
676 return this.wavelengths;
677 }
678
679 // Return the radial frequencies
680 public double[] getRadialFrequencies() {
681 return this.omega;
682 }
683
684 // Sort wavelengths into increasing order
685 // with accompanying matchingrearrangement of the magnetic permeabilities
686 // and the absorption coefficients
687 private void sortWavelengths() {
688 this.origWavelIndices = new int[this.numberOfWavelengths];
689 for (int i = 0; i < this.numberOfWavelengths; i++)
690 this.origWavelIndices[i] = i;
691 if (this.numberOfWavelengths > 1) {
692 // test if not in order
693 boolean test0 = true;
694 boolean test1 = false;
695 int ii = 1;
696 while (test0) {
697 if (this.wavelengths[ii] < this.wavelengths[ii - 1]) {
698 test0 = false;
699 test1 = true;
700 } else {
701 ii++;
702 if (ii >= this.numberOfWavelengths)
703 test0 = false;
704 }
705 }
706 if (test1) {
707 // reorder
708 ArrayList arrayl = Fmath.selectSortArrayList(wavelengths);
709 this.wavelengths = (double[]) arrayl.get(1);
710 this.origWavelIndices = (int[]) arrayl.get(2);
711
712 Complex[][] tempC = new Complex[this.numberOfWavelengths][this.numberOfLayers];
713 for (int i = 0; i < this.numberOfWavelengths; i++) {
714 for (int j = 0; j < this.numberOfLayers; j++) {
715 tempC[i][j] = this.refractiveIndices[this.origWavelIndices[i]][j];
716 }
717 }
718 this.refractiveIndices = Complex.copy(tempC);
719
720 for (int i = 0; i < this.numberOfWavelengths; i++) {
721 for (int j = 0; j < this.numberOfLayers; j++) {
722 tempC[i][j] = this.relativeMagneticPermeabilities[this.origWavelIndices[i]][j];
723 }
724 }
725 this.relativeMagneticPermeabilities = Complex.copy(tempC);
726
727 double[][] tempD = new double[this.numberOfWavelengths][this.numberOfLayers];
728 for (int i = 0; i < this.numberOfWavelengths; i++) {
729 for (int j = 0; j < this.numberOfLayers; j++) {
730 tempD[i][j] = this.absorptionCoefficients[this.origWavelIndices[i]][j];
731 }
732 }
733 this.absorptionCoefficients = tempD;
734 }
735 }
736 }
737
738 // REFRACTIVE INDICES
739
740 // Enter all individual refractive indices, as complex numbers
741 public void setRefractiveIndices(Complex[][] refractiveIndices) {
742 int n = refractiveIndices[0].length;
743 if (n != this.numberOfLayers)
744 throw new IllegalArgumentException("Number of refractive indices layers, " + n
745 + ", does not match the number of layers, " + this.numberOfLayers);
746 int m = refractiveIndices.length;
747 if (this.wavelSet) {
748 if (m != this.numberOfWavelengths)
749 throw new IllegalArgumentException("Number of refractive indices wavelength sets, " + m
750 + ", does not match the number of wavelengths already set, " + this.numberOfWavelengths);
751 }
752
753 // set refractive indices
754 this.refractiveIndices = refractiveIndices;
755 for (int i = 0; i < this.numberOfLayers; i++)
756 this.refractLayerSet[i] = true;
757 this.refractSet = true;
758 this.wavelNumberSet = true;
759
760 // calculate mean refractive index per layer
761 for (int i = 0; i < this.numberOfLayers; i++) {
762 Complex sum = Complex.zero();
763 for (int j = 0; j < this.numberOfWavelengths; j++) {
764 sum.plusEquals(this.refractiveIndices[j][i]);
765 }
766 this.meanRefractiveIndices[i] = sum.over(this.numberOfWavelengths);
767 }
768
769 // enter imaginary refractive indices if absorption coefficients have
770 // been entered
771 if (this.wavelSet && this.absorptionCoefficients != null) {
772 for (int i = 0; i < this.numberOfLayers; i++) {
773 for (int j = 0; j < this.numberOfWavelengths; j++) {
774 if (this.refractiveIndices[j][i].getImag() == 0.0D)
775 this.refractiveIndices[j][i]
776 .setImag(absorptionCoefficients[j][i] * this.wavelengths[i] / (4.0D * Math.PI));
777 }
778 }
779 }
780 // otherwise set absorption coefficients to zero
781 if (!this.absorbSet)
782 absorptionCoefficients = new double[this.numberOfWavelengths][this.numberOfLayers];
783
784 // Fill out relative magnetic permeability arrays
785 if (!this.magneticSet) {
786 if (this.meanMagneticUsed) {
787 for (int i = 0; i < this.numberOfLayers; i++) {
788 for (int j = 0; j < this.numberOfWavelengths; j++) {
789 this.relativeMagneticPermeabilities[j][i] = this.meanRelativeMagneticPermeabilities[i];
790 }
791 }
792 this.magneticSet = true;
793 } else {
794 this.relativeMagneticPermeabilities = Complex.twoDarray(this.numberOfWavelengths, this.numberOfLayers,
795 1.0D, 0.0D);
796 }
797 }
798 }
799
800 // Enter all individual refractive indices, as real numbers
801 public void setRefractiveIndices(double[][] refractiveIndices) {
802 int n = refractiveIndices[0].length;
803 if (n != this.numberOfLayers)
804 throw new IllegalArgumentException("Number of refractive indices layers, " + n
805 + ", does not match the number of layers, " + this.numberOfLayers);
806 int m = refractiveIndices.length;
807 if (this.wavelSet) {
808 if (m != this.numberOfWavelengths)
809 throw new IllegalArgumentException("Number of refractive indices wavelength sets, " + m
810 + ", does not match the number of wavelengths already set, " + this.numberOfWavelengths);
811 }
812 Complex[][] complexRefractiveIndices = Complex.twoDarray(m, n);
813 for (int i = 0; i < m; i++) {
814 for (int j = 0; j < n; j++) {
815 complexRefractiveIndices[i][j].setReal(refractiveIndices[i][j]);
816 }
817 }
818 this.setRefractiveIndices(complexRefractiveIndices);
819 }
820
821 // Enter mean refractive index for each layer, as complex numbers
822 public void setRefractiveIndices(Complex[] refractiveIndices) {
823
824 // set refractive indices
825 int n = refractiveIndices.length;
826 if (n != this.numberOfLayers)
827 throw new IllegalArgumentException("Number of refrative indices layers, " + n
828 + ", does not match the number of layers, " + this.numberOfLayers);
829 this.meanRefractiveIndices = refractiveIndices;
830 this.meanRefractUsed = true;
831
832 if (this.wavelNumberSet) {
833 // Fill out individual refractive index arrays
834 for (int i = 0; i < this.numberOfLayers; i++) {
835 for (int j = 0; j < this.numberOfWavelengths; j++) {
836 this.refractiveIndices[j][i] = this.meanRefractiveIndices[i];
837 }
838 }
839 for (int i = 0; i < this.numberOfLayers; i++)
840 this.refractLayerSet[i] = true;
841 this.refractSet = true;
842 }
843
844 // enter imaginary refractive indices if absorption coefficients have
845 // been entered
846 if (this.absorptionCoefficients != null && this.wavelSet) {
847 for (int i = 0; i < this.numberOfLayers; i++) {
848 for (int j = 0; j < this.numberOfWavelengths; j++) {
849 if (this.refractiveIndices[j][i].getImag() == 0.0D)
850 this.refractiveIndices[j][i]
851 .setImag(absorptionCoefficients[j][i] * this.wavelengths[j] / (4.0D * Math.PI));
852 }
853 }
854 }
855 // otherwise set absorption coefficients to zero
856 if (this.absorptionCoefficients == null)
857 absorptionCoefficients = new double[this.numberOfWavelengths][this.numberOfLayers];
858
859 // Fill out relative magnetic permeability arrays
860 if (!this.magneticSet) {
861 if (!this.meanMagneticUsed) {
862 if (this.wavelNumberSet) {
863 this.relativeMagneticPermeabilities = Complex.twoDarray(this.numberOfWavelengths,
864 this.numberOfLayers, 1.0D, 0.0D);
865 }
866 } else {
867 this.relativeMagneticPermeabilities = Complex.twoDarray(this.numberOfWavelengths, this.numberOfLayers);
868 for (int i = 0; i < this.numberOfLayers; i++) {
869 for (int j = 0; j < this.numberOfWavelengths; j++) {
870 this.relativeMagneticPermeabilities[j][i] = this.meanRelativeMagneticPermeabilities[i];
871 }
872 }
873 this.magneticSet = true;
874 }
875 }
876 }
877
878 // Enter mean refractive index for each layer, as real numbers
879 public void setRefractiveIndices(double[] refractiveIndices) {
880 int n = refractiveIndices.length;
881 if (n != this.numberOfLayers)
882 throw new IllegalArgumentException("Number of refrative indices, " + n
883 + ", does not match the number of layers, " + this.numberOfLayers);
884 Complex[] complexRefractiveIndices = Complex.oneDarray(n);
885 for (int i = 0; i < n; i++) {
886 complexRefractiveIndices[i].setReal(refractiveIndices[i]);
887 }
888 this.setRefractiveIndices(complexRefractiveIndices);
889
890 }
891
892 // Set refractive indices for an individual layer, as complex numbers
893 public void setRefractiveIndices(Complex[] refractiveIndices, int layerNumber) {
894 if (layerNumber < 0 || layerNumber > this.numberOfLayers)
895 throw new IllegalArgumentException(
896 "Layer number, " + layerNumber + ", must be in the range 1 to " + this.numberOfLayers);
897 int n = refractiveIndices.length;
898 if (this.wavelNumberSet) {
899 if (n != this.numberOfWavelengths)
900 throw new IllegalArgumentException("The number of refractive index wavelength values, " + n
901 + ", does not match the number of wavelengths already entered, " + this.numberOfWavelengths);
902
903 } else {
904 // Give dimensions to refractive index arrays - fill with mean if
905 // known
906 this.numberOfWavelengths = n;
907 this.wavelNumberSet = true;
908 this.refractiveIndices = Complex.twoDarray(this.numberOfLayers, this.numberOfWavelengths);
909 if (this.meanRefractUsed) {
910 for (int i = 0; i < this.numberOfLayers; i++) {
911 for (int j = 0; j < this.numberOfWavelengths; j++) {
912 this.refractiveIndices[j][i] = this.meanRefractiveIndices[i];
913 }
914 }
915 for (int i = 0; i < this.numberOfLayers; i++)
916 this.refractLayerSet[i] = true;
917 this.refractSet = true;
918 }
919 // Give dimensions to relative permeabilities arrays - fill with
920 // mean if known
921 this.relativeMagneticPermeabilities = Complex.twoDarray(this.numberOfWavelengths, this.numberOfLayers, 1.0D,
922 0.0D);
923
924 if (this.meanMagneticUsed) {
925 for (int i = 0; i < this.numberOfLayers; i++) {
926 for (int j = 0; j < this.numberOfWavelengths; j++) {
927 this.relativeMagneticPermeabilities[j][i] = this.meanRelativeMagneticPermeabilities[i];
928 }
929 }
930 this.magneticSet = true;
931 }
932 }
933
934 // fill layer values for layer identified in this method's argument list
935 layerNumber--;
936 this.refractiveIndices[layerNumber] = refractiveIndices;
937 this.refractLayerSet[layerNumber] = true;
938 int check = 0;
939 for (int i = 0; i < this.numberOfLayers; i++)
940 if (this.refractLayerSet[i])
941 check++;
942 if (check == this.numberOfLayers)
943 this.refractSet = true;
944
945 // set imaginary refractive indices for this layer if some absorption
946 // coefficients already entered
947 if (this.absorptionCoefficients != null) {
948 for (int i = 0; i < this.numberOfLayers; i++) {
949 for (int j = 0; j < this.numberOfWavelengths; j++) {
950 if (this.refractiveIndices[j][i].getImag() == 0.0D)
951 this.refractiveIndices[j][i]
952 .setImag(absorptionCoefficients[j][i] * this.wavelengths[j] / (4.0D * Math.PI));
953 }
954 }
955 }
956 // otherwise set all absorption coefficients to zero
957 if (this.absorptionCoefficients == null)
958 absorptionCoefficients = new double[this.numberOfWavelengths][this.numberOfLayers];
959
960 }
961
962 // Set refractive indices for an individual layer, as real numbers
963 public void setRefractiveIndices(double[] refractiveIndices, int layerNumber) {
964 if (layerNumber < 0 || layerNumber > this.numberOfLayers)
965 throw new IllegalArgumentException(
966 "Layer number, " + layerNumber + ", must be in the range 1 to " + this.numberOfLayers);
967 int n = refractiveIndices.length;
968 if (this.wavelNumberSet) {
969 if (n != this.numberOfWavelengths)
970 throw new IllegalArgumentException("The number of refractive index wavelength values, " + n
971 + ", does not match the number of wavelengths already entered, " + this.numberOfWavelengths);
972 }
973 Complex[] complexRefractiveIndices = Complex.oneDarray(n);
974 for (int i = 0; i < n; i++) {
975 complexRefractiveIndices[i].setReal(refractiveIndices[i]);
976 }
977 this.setRefractiveIndices(complexRefractiveIndices, layerNumber);
978 }
979
980 // Set mean refractive indices for an individual layer, as a complex number
981 public void setRefractiveIndices(Complex refractiveIndex, int layerNumber) {
982 if (this.wavelNumberSet) {
983 Complex[] complexRefractiveIndices = Complex.oneDarray(this.numberOfWavelengths);
984 for (int i = 0; i < this.numberOfWavelengths; i++) {
985 complexRefractiveIndices[i] = refractiveIndex;
986 }
987 this.setRefractiveIndices(complexRefractiveIndices, layerNumber);
988 } else {
989 this.meanRefractiveIndices[layerNumber - 1] = refractiveIndex;
990 this.meanRefractUsed = true;
991 }
992 }
993
994 // Set mean refractive indices for an individual layer, as a real number
995 public void setRefractiveIndices(double refractiveIndex, int layerNumber) {
996 Complex complexRefractiveIndex = new Complex(refractiveIndex, 0.0D);
997 this.setRefractiveIndices(complexRefractiveIndex, layerNumber);
998 }
999
1000 // Return refractive indices
1001 public Object getRefractiveIndices() {
1002 if (this.numberOfWavelengths == 1) {
1003 Complex[] ret = this.refractiveIndices[0];
1004 return (Object) ret;
1005 } else {
1006 return (Object) this.refractiveIndices;
1007 }
1008 }
1009
1010 // ABSORPTION COEFFICIENTS
1011
1012 // Enter absorption coefficients [default = 0], single wavelength
1013 public void setAbsorptionCoefficients(double[] absorptionCoefficients) {
1014 // set absorption coefficients arrays
1015 int n = absorptionCoefficients.length;
1016 if (n != this.numberOfLayers)
1017 throw new IllegalArgumentException("Number of absorption coefficients sets, " + n
1018 + ", does not match the number of layers, " + this.numberOfLayers);
1019 this.absorptionCoefficients = new double[1][n];
1020 this.absorptionCoefficients[0] = absorptionCoefficients;
1021 this.absorbSet = true;
1022
1023 if (this.refractSet) {
1024 for (int i = 0; i < this.numberOfLayers; i++) {
1025 if (this.refractiveIndices[0][i].getImag() == 0.0D)
1026 this.refractiveIndices[0][i]
1027 .setImag(this.absorptionCoefficients[0][i] * this.wavelengths[0] / (4.0D * Math.PI));
1028 }
1029 }
1030 }
1031
1032 // Enter absorption coefficients [default = 0], range of wavelengths
1033 public void setAbsorptionCoefficients(double[][] absorptionCoefficients) {
1034 // set absorption coefficients arrays
1035 int n = absorptionCoefficients[0].length;
1036 if (n != this.numberOfLayers)
1037 throw new IllegalArgumentException("Number of absorption coefficients sets, " + n
1038 + ", does not match the number of layers, " + this.numberOfLayers);
1039 int m = absorptionCoefficients.length;
1040 if (this.wavelNumberSet && m != this.numberOfWavelengths)
1041 throw new IllegalArgumentException("Number of absorption coefficients wavelengths, " + m
1042 + ", does not match the number of wavelengths already entered, " + this.numberOfWavelengths);
1043 this.absorptionCoefficients = absorptionCoefficients;
1044 this.absorbSet = true;
1045
1046 if (this.refractSet && this.wavelSet) {
1047 for (int i = 0; i < this.numberOfLayers; i++) {
1048 for (int j = 0; j < this.numberOfWavelengths; j++) {
1049 if (this.refractiveIndices[j][i].getImag() == 0.0D)
1050 this.refractiveIndices[j][i]
1051 .setImag(absorptionCoefficients[j][i] * this.wavelengths[j] / (4.0D * Math.PI));
1052 }
1053 }
1054 }
1055 }
1056
1057 // Enter absorption coefficients for a single layer [default = 0], range of
1058 // wavelengths
1059 public void setAbsorptionCoefficients(double[] absorptionCoefficients, int layerNumber) {
1060 // set absorption coefficients array
1061 int n = absorptionCoefficients.length;
1062 if (this.wavelNumberSet) {
1063 if (n != this.numberOfWavelengths)
1064 throw new IllegalArgumentException("Layer " + layerNumber
1065 + ": number of absorption coefficients wavelengths, " + n
1066 + ", does not match the number of wavelengths already entered, " + this.numberOfWavelengths);
1067 } else {
1068 this.numberOfWavelengths = n;
1069 this.refractiveIndices = Complex.twoDarray(this.numberOfWavelengths, this.numberOfLayers);
1070 this.absorptionCoefficients = new double[this.numberOfWavelengths][this.numberOfLayers];
1071 }
1072 layerNumber--;
1073 this.absorptionCoefficients[layerNumber] = absorptionCoefficients;
1074 for (int j = 0; j < this.numberOfWavelengths; j++) {
1075 if (this.refractiveIndices[j][layerNumber].getImag() == 0.0D)
1076 this.refractiveIndices[j][layerNumber]
1077 .setImag(absorptionCoefficients[j] * this.wavelengths[j] / (4.0D * Math.PI));
1078 }
1079 this.absorbSet = true;
1080 }
1081
1082 // Enter absorption coefficients for a single layer [default = 0], single
1083 // wavelength
1084 public void setAbsorptionCoefficients(double absorptionCoefficient, int layerNumber) {
1085 // set absorption coefficients array
1086 if (this.wavelNumberSet) {
1087 if (this.numberOfWavelengths != 1)
1088 throw new IllegalArgumentException("Layer " + layerNumber
1089 + ": number of absorption coefficients wavelengths, " + 1
1090 + ", does not match the number of wavelengths already entered, " + this.numberOfWavelengths);
1091 } else {
1092 this.numberOfWavelengths = 1;
1093 this.refractiveIndices = Complex.twoDarray(this.numberOfWavelengths, this.numberOfLayers);
1094 this.absorptionCoefficients = new double[this.numberOfWavelengths][this.numberOfLayers];
1095 }
1096 layerNumber--;
1097 this.absorptionCoefficients[0][layerNumber] = absorptionCoefficient;
1098 if (this.refractiveIndices[0][layerNumber].getImag() == 0.0D)
1099 this.refractiveIndices[0][layerNumber]
1100 .setImag(absorptionCoefficient * this.wavelengths[0] / (4.0D * Math.PI));
1101
1102 this.absorbSet = true;
1103 }
1104
1105 // Return absorption coefficients
1106 public Object getAbsorptionCoefficients() {
1107
1108 double[][] absC = this.absorptionCoefficients;
1109 for (int i = 0; i < this.numberOfLayers; i++) {
1110 for (int j = 0; j < this.numberOfWavelengths; j++) {
1111 absC[i][j] = 4.0D * Math.PI * this.wavelengths[j] * this.refractiveIndices[i][j].getImag();
1112 }
1113 }
1114
1115 if (this.numberOfWavelengths == 1) {
1116 double[] ret = absC[0];
1117 return (Object) ret;
1118 } else {
1119 return (Object) absC;
1120 }
1121 }
1122
1123 // RELATIVE MAGNETIC PERMEABILITIES
1124
1125 // Enter magnetic permeabilities as complex numbers [default values = 1.0]
1126 public void setRelativeMagneticPermeabilities(Complex[][] relativeMagneticPermeabilities) {
1127 int n = relativeMagneticPermeabilities[0].length;
1128 if (n != this.numberOfLayers)
1129 throw new IllegalArgumentException("Number of relative magnetic permeabilities, " + n
1130 + ", does not match the number of layers, " + this.numberOfLayers);
1131 int m = relativeMagneticPermeabilities.length;
1132 if (this.wavelNumberSet)
1133 if (m != this.numberOfWavelengths)
1134 throw new IllegalArgumentException("Number of relative magnetic permeabilities associated wavelengths, "
1135 + m + ", does not match the number of wavelengths already entered, "
1136 + this.numberOfWavelengths);
1137 this.relativeMagneticPermeabilities = relativeMagneticPermeabilities;
1138 this.magneticSet = true;
1139
1140 // calculate mean permeabilities
1141 for (int i = 0; i < this.numberOfLayers; i++) {
1142 Complex sum = Complex.zero();
1143 for (int j = 0; j < this.numberOfWavelengths; j++) {
1144 sum.plusEquals(this.relativeMagneticPermeabilities[j][i]);
1145 }
1146 this.meanRelativeMagneticPermeabilities[i] = sum.over(this.numberOfWavelengths);
1147 }
1148 }
1149
1150 // Enter magnetic permeabilities as real numbers [default values = 1.0]
1151 public void relativeMagneticPermeabilities(double[][] relativeMagneticPermeabilities) {
1152 int n = relativeMagneticPermeabilities[0].length;
1153 if (n != this.numberOfLayers)
1154 throw new IllegalArgumentException("Number of relative magnetic permeabilities, " + n
1155 + ", does not match the number of layers, " + this.numberOfLayers);
1156 int m = relativeMagneticPermeabilities.length;
1157 if (this.wavelNumberSet)
1158 if (m != this.numberOfWavelengths)
1159 throw new IllegalArgumentException("Number of relative magnetic permeabilities associated wavelengths, "
1160 + m + ", does not match the number of wavelengths already entered, "
1161 + this.numberOfWavelengths);
1162 this.relativeMagneticPermeabilities = Complex.twoDarray(m, n);
1163 for (int i = 0; i < this.numberOfLayers; i++) {
1164 for (int j = 0; j < this.numberOfWavelengths; j++) {
1165 this.relativeMagneticPermeabilities[j][i].setReal(relativeMagneticPermeabilities[j][i]);
1166 }
1167 }
1168 this.magneticSet = true;
1169
1170 // calculate mean permeabilities
1171 for (int i = 0; i < this.numberOfLayers; i++) {
1172 Complex sum = Complex.zero();
1173 for (int j = 0; j < this.numberOfWavelengths; j++) {
1174 sum.plusEquals(this.relativeMagneticPermeabilities[j][i]);
1175 }
1176 this.meanRelativeMagneticPermeabilities[i] = sum.over(this.numberOfWavelengths);
1177 }
1178 }
1179
1180 // Enter magnetic permeabilities as a mean value for each layer, complex
1181 // numbers [default values = 1.0]
1182 public void setRelativeMagneticPermeabilities(Complex[] relativeMagneticPermeabilities) {
1183 int n = relativeMagneticPermeabilities.length;
1184 if (n != this.numberOfLayers)
1185 throw new IllegalArgumentException("Number of relative magnetic permeabilities, " + n
1186 + ", does not match the number of layers, " + this.numberOfLayers);
1187 this.meanRelativeMagneticPermeabilities = relativeMagneticPermeabilities;
1188 this.meanMagneticUsed = true;
1189 if (this.wavelNumberSet)
1190 for (int i = 0; i < this.numberOfWavelengths; i++)
1191 this.relativeMagneticPermeabilities[i] = Complex.copy(relativeMagneticPermeabilities);
1192 }
1193
1194 // Enter magnetic permeabilities as a mean value for each layer, real
1195 // numbers [default values = 1.0]
1196 public void setRelativeMagneticPermeabilities(double[] relativeMagneticPermeabilities) {
1197 int n = relativeMagneticPermeabilities.length;
1198 if (n != this.numberOfLayers)
1199 throw new IllegalArgumentException("Number of relative magnetic permeabilities, " + n
1200 + ", does not match the number of layers, " + this.numberOfLayers);
1201 for (int i = 0; i < n; i++)
1202 this.meanRelativeMagneticPermeabilities[i].setReal(relativeMagneticPermeabilities[i]);
1203 this.meanMagneticUsed = true;
1204 if (this.wavelNumberSet)
1205 for (int i = 0; i < this.numberOfWavelengths; i++)
1206 this.relativeMagneticPermeabilities[i] = Complex.copy(this.meanRelativeMagneticPermeabilities);
1207
1208 }
1209
1210 // Enter magnetic permeabilities for a single layer, complex numbers
1211 // [default values = 1.0]
1212 public void setRelativeMagneticPermeabilities(Complex[] relativeMagneticPermeabilities, int layerNumber) {
1213 int n = relativeMagneticPermeabilities.length;
1214 if (this.wavelNumberSet) {
1215 if (n != this.numberOfWavelengths)
1216 throw new IllegalArgumentException("Layer " + layerNumber
1217 + ": number of relative magnetic permeabilities associated wavelengths, " + n
1218 + ", does not match the number of wavelengths already entered, " + this.numberOfWavelengths);
1219 }
1220 if (this.relativeMagneticPermeabilities == null)
1221 this.relativeMagneticPermeabilities = Complex.twoDarray(n, this.numberOfLayers);
1222 this.relativeMagneticPermeabilities[layerNumber - 1] = relativeMagneticPermeabilities;
1223 Complex sum = Complex.zero();
1224 for (int i = 0; i < n; i++)
1225 sum.plusEquals(this.relativeMagneticPermeabilities[i][layerNumber - 1]);
1226 this.meanRelativeMagneticPermeabilities[layerNumber - 1] = sum.over(n);
1227 }
1228
1229 // Enter magnetic permeabilities for a single layer, real numbers [default
1230 // values = 1.0]
1231 public void setRelativeMagneticPermeabilities(double[] relativeMagneticPermeabilities, int layerNumber) {
1232 int n = relativeMagneticPermeabilities.length;
1233 if (this.wavelNumberSet) {
1234 if (n != this.numberOfWavelengths)
1235 throw new IllegalArgumentException("Layer " + layerNumber
1236 + ": number of relative magnetic permeabilities associated wavelengths, " + n
1237 + ", does not match the number of wavelengths already entered, " + this.numberOfWavelengths);
1238 }
1239 if (this.relativeMagneticPermeabilities == null)
1240 this.relativeMagneticPermeabilities = Complex.twoDarray(n, this.numberOfLayers);
1241 for (int i = 0; i < n; i++)
1242 this.relativeMagneticPermeabilities[i][layerNumber - 1].setReal(relativeMagneticPermeabilities[i]);
1243 Complex sum = Complex.zero();
1244 for (int i = 0; i < n; i++)
1245 sum.plusEquals(this.relativeMagneticPermeabilities[i][layerNumber - 1]);
1246 this.meanRelativeMagneticPermeabilities[layerNumber - 1] = sum.over(n);
1247 }
1248
1249 // Enter mean magnetic permeability for a single layer, complex number
1250 // [default values = 1.0]
1251 public void setRelativeMagneticPermeabilities(Complex relativeMagneticPermeability, int layerNumber) {
1252 this.meanRelativeMagneticPermeabilities[layerNumber - 1] = relativeMagneticPermeability;
1253 this.meanMagneticUsed = true;
1254 if (this.relativeMagneticPermeabilities != null) {
1255 int n = this.relativeMagneticPermeabilities[0].length;
1256 for (int i = 0; i < n; i++)
1257 this.relativeMagneticPermeabilities[i][layerNumber - 1] = relativeMagneticPermeability;
1258 }
1259 }
1260
1261 // Enter mean magnetic permeability for a single layer, real number [default
1262 // values = 1.0]
1263 public void setRelativeMagneticPermeabilities(double relativeMagneticPermeability, int layerNumber) {
1264 this.meanRelativeMagneticPermeabilities[layerNumber - 1].setReal(relativeMagneticPermeability);
1265 this.meanMagneticUsed = true;
1266 if (this.relativeMagneticPermeabilities != null) {
1267 int n = this.relativeMagneticPermeabilities[0].length;
1268 for (int i = 0; i < n; i++)
1269 this.relativeMagneticPermeabilities[i][layerNumber
1270 - 1] = this.meanRelativeMagneticPermeabilities[layerNumber - 1];
1271 }
1272 }
1273
1274 // Return relative magnetic permeabilities
1275 public Object getRelativeMagneticPermeabilities() {
1276 if (this.numberOfWavelengths == 1) {
1277 Complex[] ret = this.relativeMagneticPermeabilities[0];
1278 return (Object) ret;
1279 } else {
1280 return (Object) this.relativeMagneticPermeabilities;
1281 }
1282 }
1283
1284 // REFLECTIVITIES AND REFLECTION COEFFICIENTS
1285
1286 // Return the reflectivities
1287 public Object getReflectivities() {
1288 this.checkWhichCalculation();
1289 if (this.singleReflectCalculated) {
1290 return (Object) this.reflectivities[0];
1291 } else {
1292 if (this.angularReflectCalculated) {
1293 return (Object) this.reflectivities[0];
1294 } else {
1295 if (this.wavelengthReflectCalculated) {
1296 double[] ret = new double[this.numberOfWavelengths];
1297 for (int i = 0; i < this.numberOfWavelengths; i++)
1298 ret[i] = this.reflectivities[i][0];
1299 return (Object) ret;
1300 } else {
1301 if (this.wavelengthAndAngularReflectCalculated) {
1302 return (Object) this.reflectivities;
1303 } else {
1304 return null;
1305 }
1306 }
1307 }
1308 }
1309 }
1310
1311 // Return the TE mode reflection coefficients
1312 public Object getTEreflectionCoefficients() {
1313 this.checkWhichCalculation();
1314 if (this.singleReflectCalculated) {
1315 return (Object) this.reflectCoeffTE[0];
1316 } else {
1317 if (this.angularReflectCalculated) {
1318 return (Object) this.reflectCoeffTE[0];
1319 } else {
1320 if (this.wavelengthReflectCalculated) {
1321 Complex[] ret = Complex.oneDarray(this.numberOfWavelengths);
1322 for (int i = 0; i < this.numberOfWavelengths; i++)
1323 ret[i] = this.reflectCoeffTE[i][0];
1324 return (Object) ret;
1325 } else {
1326 if (this.wavelengthAndAngularReflectCalculated) {
1327 return (Object) this.reflectCoeffTE;
1328 } else {
1329 return null;
1330 }
1331 }
1332 }
1333 }
1334 }
1335
1336 // Return the TM mode reflection coefficients
1337 public Object getTMreflectionCoefficients() {
1338 this.checkWhichCalculation();
1339 if (this.singleReflectCalculated) {
1340 return (Object) this.reflectCoeffTM[0];
1341 } else {
1342 if (this.angularReflectCalculated) {
1343 return (Object) this.reflectCoeffTM[0];
1344 } else {
1345 if (this.wavelengthReflectCalculated) {
1346 Complex[] ret = Complex.oneDarray(this.numberOfWavelengths);
1347 for (int i = 0; i < this.numberOfWavelengths; i++)
1348 ret[i] = this.reflectCoeffTM[i][0];
1349 return (Object) ret;
1350 } else {
1351 if (this.wavelengthAndAngularReflectCalculated) {
1352 return (Object) this.reflectCoeffTM;
1353 } else {
1354 return null;
1355 }
1356 }
1357 }
1358 }
1359 }
1360
1361 // TRANSMISSIVITIES, TRANSMISSION COEFFICIENTS AND TRANSMISSION ANGLES
1362
1363 // Return the transmissivities
1364 public Object getTransmissivities() {
1365 this.checkWhichCalculation();
1366 if (this.singleReflectCalculated) {
1367 return (Object) this.transmissivities[0];
1368 } else {
1369 if (this.angularReflectCalculated) {
1370 return (Object) this.transmissivities[0];
1371 } else {
1372 if (this.wavelengthReflectCalculated) {
1373 double[] ret = new double[this.numberOfWavelengths];
1374 for (int i = 0; i < this.numberOfWavelengths; i++)
1375 ret[i] = this.transmissivities[i][0];
1376 return (Object) ret;
1377 } else {
1378 if (this.wavelengthAndAngularReflectCalculated) {
1379 return (Object) this.transmissivities;
1380 } else {
1381 return null;
1382 }
1383 }
1384 }
1385 }
1386 }
1387
1388 // Return the power loss on transmission as decibels
1389 public Object getPowerLoss() {
1390 this.checkWhichCalculation();
1391 if (this.singleReflectCalculated) {
1392 return (Object) this.powerLosses[0];
1393 } else {
1394 if (this.angularReflectCalculated) {
1395 return (Object) this.powerLosses[0];
1396 } else {
1397 if (this.wavelengthReflectCalculated) {
1398 double[] ret = new double[this.numberOfWavelengths];
1399 for (int i = 0; i < this.numberOfWavelengths; i++)
1400 ret[i] = this.powerLosses[i][0];
1401 return (Object) ret;
1402 } else {
1403 if (this.wavelengthAndAngularReflectCalculated) {
1404 return (Object) this.powerLosses;
1405 } else {
1406 return null;
1407 }
1408 }
1409 }
1410 }
1411 }
1412
1413 // Return the angle of transmitted beam with respect to normal (radians)
1414 public Object getTransmissionAnglesInRadians() {
1415 this.checkWhichCalculation();
1416 if (this.singleReflectCalculated) {
1417 return (Object) this.transmitAnglesRad[0];
1418 } else {
1419 if (this.angularReflectCalculated) {
1420 return (Object) this.transmitAnglesRad[0];
1421 } else {
1422 if (this.wavelengthReflectCalculated) {
1423 double[] ret = new double[this.numberOfWavelengths];
1424 for (int i = 0; i < this.numberOfWavelengths; i++)
1425 ret[i] = this.transmitAnglesRad[i][0];
1426 return (Object) ret;
1427 } else {
1428 if (this.wavelengthAndAngularReflectCalculated) {
1429 return (Object) this.transmitAnglesRad;
1430 } else {
1431 return null;
1432 }
1433 }
1434 }
1435 }
1436 }
1437
1438 // Return the angle of transmitted beam with respect to normal (degrees)
1439 public Object getTransmissionAnglesInDegrees() {
1440 this.checkWhichCalculation();
1441 if (this.singleReflectCalculated) {
1442 return (Object) this.transmitAnglesDeg[0];
1443 } else {
1444 if (this.angularReflectCalculated) {
1445 return (Object) this.transmitAnglesDeg[0];
1446 } else {
1447 if (this.wavelengthReflectCalculated) {
1448 double[] ret = new double[this.numberOfWavelengths];
1449 for (int i = 0; i < this.numberOfWavelengths; i++)
1450 ret[i] = this.transmitAnglesDeg[i][0];
1451 return (Object) ret;
1452 } else {
1453 if (this.wavelengthAndAngularReflectCalculated) {
1454 return (Object) this.transmitAnglesDeg;
1455 } else {
1456 return null;
1457 }
1458 }
1459 }
1460 }
1461 }
1462
1463 // Return the TE mode transmission coefficients
1464 public Object getTEtransmissionCoefficients() {
1465 this.checkWhichCalculation();
1466 if (this.singleReflectCalculated) {
1467 return (Object) this.transmitCoeffTE[0];
1468 } else {
1469 if (this.angularReflectCalculated) {
1470 return (Object) this.transmitCoeffTE[0];
1471 } else {
1472 if (this.wavelengthReflectCalculated) {
1473 Complex[] ret = Complex.oneDarray(this.numberOfWavelengths);
1474 for (int i = 0; i < this.numberOfWavelengths; i++)
1475 ret[i] = this.transmitCoeffTE[i][0];
1476 return (Object) ret;
1477 } else {
1478 if (this.wavelengthAndAngularReflectCalculated) {
1479 return (Object) this.transmitCoeffTE;
1480 } else {
1481 return null;
1482 }
1483 }
1484 }
1485 }
1486 }
1487
1488 // Return the TM mode transmission coefficients
1489 public Object getTMtransmissionCoefficients() {
1490 this.checkWhichCalculation();
1491 if (this.singleReflectCalculated) {
1492 return (Object) this.transmitCoeffTM[0];
1493 } else {
1494 if (this.angularReflectCalculated) {
1495 return (Object) this.transmitCoeffTM[0];
1496 } else {
1497 if (this.wavelengthReflectCalculated) {
1498 Complex[] ret = Complex.oneDarray(this.numberOfWavelengths);
1499 for (int i = 0; i < this.numberOfWavelengths; i++)
1500 ret[i] = this.transmitCoeffTM[i][0];
1501 return (Object) ret;
1502 } else {
1503 if (this.wavelengthAndAngularReflectCalculated) {
1504 return (Object) this.transmitCoeffTM;
1505 } else {
1506 return null;
1507 }
1508 }
1509 }
1510 }
1511 }
1512
1513 // PHASE SHIFTS
1514
1515 // Return the phase shifts on reflection (TE mode)in degrees
1516 public Object getTEreflectionPhaseShiftDeg() {
1517 this.checkWhichCalculation();
1518 if (this.singleReflectCalculated) {
1519 return (Object) this.reflectPhaseShiftDegTE[0];
1520 } else {
1521 if (this.angularReflectCalculated) {
1522 return (Object) this.reflectPhaseShiftDegTE[0];
1523 } else {
1524 if (this.wavelengthReflectCalculated) {
1525 double[] ret = new double[this.numberOfWavelengths];
1526 for (int i = 0; i < this.numberOfWavelengths; i++)
1527 ret[i] = this.reflectPhaseShiftDegTE[i][0];
1528 return (Object) ret;
1529 } else {
1530 if (this.wavelengthAndAngularReflectCalculated) {
1531 return (Object) this.reflectPhaseShiftDegTE;
1532 } else {
1533 return null;
1534 }
1535 }
1536 }
1537 }
1538 }
1539
1540 // Return the phase shifts on reflection (TE mode)in radians
1541 public Object getTEreflectionPhaseShiftRad() {
1542 this.checkWhichCalculation();
1543 if (this.singleReflectCalculated) {
1544 return (Object) this.reflectPhaseShiftRadTE[0];
1545 } else {
1546 if (this.angularReflectCalculated) {
1547 return (Object) this.reflectPhaseShiftRadTE[0];
1548 } else {
1549 if (this.wavelengthReflectCalculated) {
1550 double[] ret = new double[this.numberOfWavelengths];
1551 for (int i = 0; i < this.numberOfWavelengths; i++)
1552 ret[i] = this.reflectPhaseShiftRadTE[i][0];
1553 return (Object) ret;
1554 } else {
1555 if (this.wavelengthAndAngularReflectCalculated) {
1556 return (Object) this.reflectPhaseShiftRadTE;
1557 } else {
1558 return null;
1559 }
1560 }
1561 }
1562 }
1563 }
1564
1565 // Return the phase shifts on reflection (TM mode)in degrees
1566 public Object getTMreflectionPhaseShiftDeg() {
1567 this.checkWhichCalculation();
1568 if (this.singleReflectCalculated) {
1569 return (Object) this.reflectPhaseShiftDegTM[0];
1570 } else {
1571 if (this.angularReflectCalculated) {
1572 return (Object) this.reflectPhaseShiftDegTM[0];
1573 } else {
1574 if (this.wavelengthReflectCalculated) {
1575 double[] ret = new double[this.numberOfWavelengths];
1576 for (int i = 0; i < this.numberOfWavelengths; i++)
1577 ret[i] = this.reflectPhaseShiftDegTM[i][0];
1578 return (Object) ret;
1579 } else {
1580 if (this.wavelengthAndAngularReflectCalculated) {
1581 return (Object) this.reflectPhaseShiftDegTM;
1582 } else {
1583 return null;
1584 }
1585 }
1586 }
1587 }
1588 }
1589
1590 // Return the phase shifts on reflection (TM mode)in radians
1591 public Object getTMreflectionPhaseShiftRad() {
1592 this.checkWhichCalculation();
1593 if (this.singleReflectCalculated) {
1594 return (Object) this.reflectPhaseShiftRadTM[0];
1595 } else {
1596 if (this.angularReflectCalculated) {
1597 return (Object) this.reflectPhaseShiftRadTM[0];
1598 } else {
1599 if (this.wavelengthReflectCalculated) {
1600 double[] ret = new double[this.numberOfWavelengths];
1601 for (int i = 0; i < this.numberOfWavelengths; i++)
1602 ret[i] = this.reflectPhaseShiftRadTM[i][0];
1603 return (Object) ret;
1604 } else {
1605 if (this.wavelengthAndAngularReflectCalculated) {
1606 return (Object) this.reflectPhaseShiftRadTM;
1607 } else {
1608 return null;
1609 }
1610 }
1611 }
1612 }
1613 }
1614
1615 // Return the phase shifts on transmission (TE mode)in degrees
1616 public Object getTEtransmissionPhaseShiftDeg() {
1617 this.checkWhichCalculation();
1618 if (this.singleReflectCalculated) {
1619 return (Object) this.transmitPhaseShiftDegTE[0];
1620 } else {
1621 if (this.angularReflectCalculated) {
1622 return (Object) this.transmitPhaseShiftDegTE[0];
1623 } else {
1624 if (this.wavelengthReflectCalculated) {
1625 double[] ret = new double[this.numberOfWavelengths];
1626 for (int i = 0; i < this.numberOfWavelengths; i++)
1627 ret[i] = this.transmitPhaseShiftDegTE[i][0];
1628 return (Object) ret;
1629 } else {
1630 if (this.wavelengthAndAngularReflectCalculated) {
1631 return (Object) this.transmitPhaseShiftDegTE;
1632 } else {
1633 return null;
1634 }
1635 }
1636 }
1637 }
1638 }
1639
1640 // Return the phase shifts on transmission (TE mode)in radians
1641 public Object getTEtransmissionPhaseShiftRad() {
1642 this.checkWhichCalculation();
1643 if (this.singleReflectCalculated) {
1644 return (Object) this.transmitPhaseShiftRadTE[0];
1645 } else {
1646 if (this.angularReflectCalculated) {
1647 return (Object) this.transmitPhaseShiftRadTE[0];
1648 } else {
1649 if (this.wavelengthReflectCalculated) {
1650 double[] ret = new double[this.numberOfWavelengths];
1651 for (int i = 0; i < this.numberOfWavelengths; i++)
1652 ret[i] = this.transmitPhaseShiftRadTE[i][0];
1653 return (Object) ret;
1654 } else {
1655 if (this.wavelengthAndAngularReflectCalculated) {
1656 return (Object) this.transmitPhaseShiftRadTE;
1657 } else {
1658 return null;
1659 }
1660 }
1661 }
1662 }
1663 }
1664
1665 // Return the phase shifts on transmission (TM mode)in degrees
1666 public Object getTMtransmissionPhaseShiftDeg() {
1667 this.checkWhichCalculation();
1668 if (this.singleReflectCalculated) {
1669 return (Object) this.transmitPhaseShiftDegTM[0];
1670 } else {
1671 if (this.angularReflectCalculated) {
1672 return (Object) this.transmitPhaseShiftDegTM[0];
1673 } else {
1674 if (this.wavelengthReflectCalculated) {
1675 double[] ret = new double[this.numberOfWavelengths];
1676 for (int i = 0; i < this.numberOfWavelengths; i++)
1677 ret[i] = this.transmitPhaseShiftDegTM[i][0];
1678 return (Object) ret;
1679 } else {
1680 if (this.wavelengthAndAngularReflectCalculated) {
1681 return (Object) this.transmitPhaseShiftDegTM;
1682 } else {
1683 return null;
1684 }
1685 }
1686 }
1687 }
1688 }
1689
1690 // Return the phase shifts on transmission (TM mode)in radians
1691 public Object getTMtransmissionPhaseShiftRad() {
1692 this.checkWhichCalculation();
1693 if (this.singleReflectCalculated) {
1694 return (Object) this.transmitPhaseShiftRadTM[0];
1695 } else {
1696 if (this.angularReflectCalculated) {
1697 return (Object) this.transmitPhaseShiftRadTM[0];
1698 } else {
1699 if (this.wavelengthReflectCalculated) {
1700 double[] ret = new double[this.numberOfWavelengths];
1701 for (int i = 0; i < this.numberOfWavelengths; i++)
1702 ret[i] = this.transmitPhaseShiftRadTM[i][0];
1703 return (Object) ret;
1704 } else {
1705 if (this.wavelengthAndAngularReflectCalculated) {
1706 return (Object) this.transmitPhaseShiftRadTM;
1707 } else {
1708 return null;
1709 }
1710 }
1711 }
1712 }
1713 }
1714
1715 // EVANESCENT FIELDS
1716
1717 // Return the integrated evanescent fields
1718 public Object getEvanescentFields(double fieldDistance) {
1719 this.fieldDistance = fieldDistance;
1720 return getEvanescentFields();
1721 }
1722
1723 // Return the integrated evanescent fields - default field depth
1724 // (POSITIVE_INFINITY)
1725 public Object getEvanescentFields() {
1726 this.checkWhichCalculation();
1727 if (this.singleReflectCalculated) {
1728 return (Object) this.evanescentFields[0];
1729 } else {
1730 if (this.angularReflectCalculated) {
1731 return (Object) this.evanescentFields[0];
1732 } else {
1733 if (this.wavelengthReflectCalculated) {
1734 double[] ret = new double[this.numberOfWavelengths];
1735 for (int i = 0; i < this.numberOfWavelengths; i++)
1736 ret[i] = this.evanescentFields[i][0];
1737 return (Object) ret;
1738 } else {
1739 if (this.wavelengthAndAngularReflectCalculated) {
1740 return (Object) this.evanescentFields;
1741 } else {
1742 return null;
1743 }
1744 }
1745 }
1746 }
1747 }
1748
1749 // Return the evanescent field penetration depths
1750 public Object getPenetrationDepths() {
1751 this.checkWhichCalculation();
1752 if (this.singleReflectCalculated) {
1753 return (Object) this.penetrationDepths[0];
1754 } else {
1755 if (this.angularReflectCalculated) {
1756 return (Object) this.penetrationDepths[0];
1757 } else {
1758 if (this.wavelengthReflectCalculated) {
1759 double[] ret = new double[this.numberOfWavelengths];
1760 for (int i = 0; i < this.numberOfWavelengths; i++)
1761 ret[i] = this.penetrationDepths[i][0];
1762 return (Object) ret;
1763 } else {
1764 if (this.wavelengthAndAngularReflectCalculated) {
1765 return (Object) this.penetrationDepths;
1766 } else {
1767 return null;
1768 }
1769 }
1770 }
1771 }
1772 }
1773
1774 // WAVE VECTORS ko, k, kx and kz
1775
1776 // Return the ko vectors
1777 public Object getKoVectors() {
1778 this.checkWhichCalculation();
1779 if (this.singleReflectCalculated) {
1780 return (Object) this.koVector[0][0][0];
1781 } else {
1782 if (this.angularReflectCalculated) {
1783 return (Object) this.koVector[0][0][0];
1784 } else {
1785 if (this.wavelengthReflectCalculated) {
1786 Complex[] ret = Complex.oneDarray(this.numberOfWavelengths);
1787 for (int i = 0; i < this.numberOfWavelengths; i++) {
1788 ret[i] = this.koVector[i][0][0];
1789 }
1790 return (Object) ret;
1791 } else {
1792 if (this.wavelengthAndAngularReflectCalculated) {
1793 Complex[] ret = Complex.oneDarray(this.numberOfWavelengths);
1794 for (int i = 0; i < this.numberOfWavelengths; i++) {
1795 ret[i] = this.koVector[i][0][0];
1796 }
1797 return (Object) ret;
1798 } else {
1799 return null;
1800 }
1801 }
1802 }
1803 }
1804 }
1805
1806 // Return the kz vectors
1807 public Object getKzVectors() {
1808 this.checkWhichCalculation();
1809 if (this.singleReflectCalculated) {
1810 return (Object) this.kzVector[0][0][0];
1811 } else {
1812 if (this.angularReflectCalculated) {
1813 Complex[] ret = Complex.oneDarray(this.numberOfIncidentAngles);
1814 for (int i = 0; i < this.numberOfIncidentAngles; i++) {
1815 ret[i] = this.kzVector[0][i][0];
1816 }
1817 return (Object) ret;
1818 } else {
1819 if (this.wavelengthReflectCalculated) {
1820 Complex[] ret = Complex.oneDarray(this.numberOfWavelengths);
1821 for (int i = 0; i < this.numberOfWavelengths; i++) {
1822 ret[i] = this.kzVector[i][0][0];
1823 }
1824 return (Object) ret;
1825 } else {
1826 if (this.wavelengthAndAngularReflectCalculated) {
1827 Complex[][] ret = Complex.twoDarray(this.numberOfWavelengths, this.numberOfIncidentAngles);
1828 for (int i = 0; i < this.numberOfWavelengths; i++) {
1829 for (int j = 0; j < this.numberOfIncidentAngles; j++) {
1830 ret[i][j] = this.kzVector[i][j][0];
1831 }
1832 }
1833 return (Object) ret;
1834 } else {
1835 return null;
1836 }
1837 }
1838 }
1839 }
1840 }
1841
1842 // Return the k vectors
1843 public Object getKvectors() {
1844 this.checkWhichCalculation();
1845 if (this.singleReflectCalculated) {
1846 return (Object) this.kVector[0][0];
1847 } else {
1848 if (this.angularReflectCalculated) {
1849 return (Object) this.kVector[0];
1850 } else {
1851 if (this.wavelengthReflectCalculated) {
1852 Complex[][] ret = Complex.twoDarray(this.numberOfWavelengths, this.numberOfLayers);
1853 for (int i = 0; i < this.numberOfWavelengths; i++) {
1854 for (int j = 0; i < this.numberOfLayers; i++) {
1855 ret[i][j] = this.kVector[i][0][j];
1856 }
1857 }
1858 return (Object) ret;
1859 } else {
1860 if (this.wavelengthAndAngularReflectCalculated) {
1861 Complex[][] ret = Complex.twoDarray(this.numberOfWavelengths, this.numberOfLayers);
1862 for (int i = 0; i < this.numberOfWavelengths; i++) {
1863 for (int j = 0; i < this.numberOfLayers; i++) {
1864 ret[i][j] = this.kVector[i][0][j];
1865 }
1866 }
1867 return (Object) ret;
1868 } else {
1869 return null;
1870 }
1871 }
1872 }
1873 }
1874 }
1875
1876 // Return the kx vectors
1877 public Object getKxVectors() {
1878 this.checkWhichCalculation();
1879 if (this.singleReflectCalculated) {
1880 return (Object) this.kxVector[0][0];
1881 } else {
1882 if (this.angularReflectCalculated) {
1883 return (Object) this.kxVector[0];
1884 } else {
1885 if (this.wavelengthReflectCalculated) {
1886 Complex[][] ret = Complex.twoDarray(this.numberOfWavelengths, this.numberOfLayers);
1887 for (int i = 0; i < this.numberOfWavelengths; i++) {
1888 for (int j = 0; i < this.numberOfLayers; i++) {
1889 ret[i][j] = this.kxVector[i][0][j];
1890 }
1891 }
1892 return (Object) ret;
1893 } else {
1894 if (this.wavelengthAndAngularReflectCalculated) {
1895 return (Object) this.kxVector;
1896 } else {
1897 return null;
1898 }
1899 }
1900 }
1901 }
1902 }
1903
1904 // METHODS THAT PLOT THE SIMULATIONS
1905
1906 // Reset wavelength axis to frequency axis
1907 public void resetPlotAxisAsFrequency() {
1908 this.wavelengthAxisOption = 2;
1909 }
1910
1911 // Reset wavelength axis to frequency axis
1912 public void resetPlotAxisAsRadians() {
1913 this.wavelengthAxisOption = 3;
1914 }
1915
1916 // Reset wavelength axis to frequency axis
1917 public void resetPlotAxisAsWavelength() {
1918 this.wavelengthAxisOption = 1;
1919 }
1920
1921 // Calculation and plotting of the reflectivities for a single or multiple
1922 // wavelengths and a range of incident angles entered
1923 // No user legend provided
1924 public void plotReflectivities() {
1925 String legend = "Polarisation mode: " + this.mode;
1926 this.plotReflectivities(legend);
1927 }
1928
1929 // Calculation and plotting of the reflectivities for a single or multiple
1930 // wavelengths and a range of incident angles entered
1931 public void plotReflectivities(String legend) {
1932 this.checkWhichCalculation();
1933 if (this.singleReflectCalculated)
1934 throw new IllegalArgumentException("Plot methods require more than one data point");
1935
1936 String graphLegendExtra = " Reflectivities";
1937 String yLegend = "Reflectivity";
1938 String yUnits = " ";
1939 plotSimulation(legend, graphLegendExtra, yLegend, yUnits, (Object) this.reflectivities);
1940 }
1941
1942 // Calculation and plotting of the transmissivities for a single or multiple
1943 // wavelengths and a range of incident angles entered
1944 // No user legend provided
1945 public void plotTransmissivities() {
1946 String legend = "Polarisation mode: " + this.mode;
1947 this.plotTransmissivities(legend);
1948 }
1949
1950 // Calculation and plotting of the transmissivities for a single or multiple
1951 // wavelengths and a range of incident angles entered
1952 public void plotTransmissivities(String legend) {
1953 this.checkWhichCalculation();
1954 if (this.singleReflectCalculated)
1955 throw new IllegalArgumentException("Plot methods require more than one data point");
1956
1957 String graphLegendExtra = " Transmissivities";
1958 String yLegend = "Transmissivity";
1959 String yUnits = " ";
1960 plotSimulation(legend, graphLegendExtra, yLegend, yUnits, (Object) this.transmissivities);
1961 }
1962
1963 // Calculation and plotting of the power losses on transmission for a single
1964 // or multiple wavelengths and a range of incident angles entered
1965 // No user legend provided
1966 public void plotPowerLosses() {
1967 String legend = "Polarisation mode: " + this.mode;
1968 this.plotPowerLosses(legend);
1969 }
1970
1971 // Calculation and plotting of the power losses on transmission for a single
1972 // or multiple wavelengths and a range of incident angles entered
1973 public void plotPowerLosses(String legend) {
1974 this.checkWhichCalculation();
1975 if (this.singleReflectCalculated)
1976 throw new IllegalArgumentException("Plot methods require more than one data point");
1977
1978 String graphLegendExtra = " Power Losses in decibels relative to an incident power of 1 mW";
1979 String yLegend = "Power Losses";
1980 String yUnits = "dBm";
1981
1982 plotSimulation(legend, graphLegendExtra, yLegend, yUnits, (Object) this.powerLosses);
1983 }
1984
1985 // Calculation and plotting of the transmission angles for a single or
1986 // multiple wavelengths and a range of incident angles entered
1987 // No user legend provided
1988 public void plotTransmissionAngles() {
1989 String legend = "Polarisation mode: " + this.mode;
1990 this.plotTransmissionAngles(legend);
1991 }
1992
1993 // Calculation and plotting of the transmission angles for a single or
1994 // multiple wavelengths and a range of incident angles entered
1995 public void plotTransmissionAngles(String legend) {
1996 this.checkWhichCalculation();
1997 if (this.singleReflectCalculated)
1998 throw new IllegalArgumentException("Plot methods require more than one data point");
1999
2000 String graphLegendExtra = " Transmission angles (degrees)";
2001 String yLegend = "Transmission angle";
2002 String yUnits = "degrees";
2003 plotSimulation(legend, graphLegendExtra, yLegend, yUnits, (Object) this.transmitAnglesDeg);
2004 }
2005
2006 // Calculation and plotting of the absolute values of TE reflection
2007 // coefficients for a single or multiple wavelengths and a range of incident
2008 // angles entered
2009 // No user legend provided
2010 public void plotAbsTEreflectionCoefficients() {
2011 String legend = "Polarisation mode: " + this.mode;
2012 this.plotAbsTEreflectionCoefficients(legend);
2013 }
2014
2015 // Calculation and plotting of the absolute values of TE reflection
2016 // coefficients for a single or multiple wavelengths and a range of incident
2017 // angles entered
2018 public void plotAbsTEreflectionCoefficients(String legend) {
2019 this.checkWhichCalculation();
2020 if (this.singleReflectCalculated)
2021 throw new IllegalArgumentException("Plot methods require more than one data point");
2022
2023 if (teFraction == 0.0D) {
2024 System.out.println("No TE transmission coefficient plot displayed as no light in the TE mode");
2025 } else {
2026 double[][] absTEr = new double[numberOfWavelengths][this.numberOfIncidentAngles];
2027 for (int i = 0; i < this.numberOfWavelengths; i++) {
2028 for (int j = 0; j < this.numberOfIncidentAngles; j++) {
2029 absTEr[i][j] = this.reflectCoeffTE[i][j].abs();
2030 }
2031 }
2032
2033 String graphLegendExtra = " Absolute values of the TE reflection coefficients";
2034 String yLegend = "|TE Reflection Coefficient|";
2035 String yUnits = " ";
2036
2037 plotSimulation(legend, graphLegendExtra, yLegend, yUnits, (Object) absTEr);
2038 }
2039 }
2040
2041 // Calculation and plotting of the absolute values of TM reflection
2042 // coefficients for a single or multiple wavelengths and a range of incident
2043 // angles entered
2044 // No user legend provided
2045 public void plotAbsTMreflectionCoefficients() {
2046 String legend = "Polarisation mode: " + this.mode;
2047 this.plotAbsTMreflectionCoefficients(legend);
2048 }
2049
2050 // Calculation and plotting of the absolute values of TM reflection
2051 // coefficients for a single or multiple wavelengths and a range of incident
2052 // angles entered
2053 public void plotAbsTMreflectionCoefficients(String legend) {
2054 this.checkWhichCalculation();
2055 if (this.singleReflectCalculated)
2056 throw new IllegalArgumentException("Plot methods require more than one data point");
2057
2058 if (tmFraction == 0.0D) {
2059 System.out.println("No TM transmission coefficient plot displayed as no light in the TM mode");
2060 } else {
2061 double[][] absTMr = new double[numberOfWavelengths][this.numberOfIncidentAngles];
2062 for (int i = 0; i < this.numberOfWavelengths; i++) {
2063 for (int j = 0; j < this.numberOfIncidentAngles; j++) {
2064 absTMr[i][j] = this.reflectCoeffTM[i][j].abs();
2065 }
2066 }
2067
2068 String graphLegendExtra = " Absolute values of the TM reflection coefficients";
2069 String yLegend = "|TM Reflection Coefficient|";
2070 String yUnits = " ";
2071
2072 plotSimulation(legend, graphLegendExtra, yLegend, yUnits, (Object) absTMr);
2073 }
2074 }
2075
2076 // Calculation and plotting of the absolute values of TE transmission
2077 // coefficients for a single or multiple wavelengths and a range of incident
2078 // angles entered
2079 // No user legend provided
2080 public void plotAbsTEtransmissionCoefficients() {
2081 String legend = "Polarisation mode: " + this.mode;
2082 this.plotAbsTEtransmissionCoefficients(legend);
2083 }
2084
2085 // Calculation and plotting of the absolute values of TE transmission
2086 // coefficients for a single or multiple wavelengths and a range of incident
2087 // angles entered
2088 public void plotAbsTEtransmissionCoefficients(String legend) {
2089 this.checkWhichCalculation();
2090 if (this.singleReflectCalculated)
2091 throw new IllegalArgumentException("Plot methods require more than one data point");
2092
2093 if (teFraction == 0.0D) {
2094 System.out.println("No TE transmission coefficient plot displayed as no light in the TE mode");
2095 } else {
2096 double[][] absTEt = new double[numberOfWavelengths][this.numberOfIncidentAngles];
2097 for (int i = 0; i < this.numberOfWavelengths; i++) {
2098 for (int j = 0; j < this.numberOfIncidentAngles; j++) {
2099 absTEt[i][j] = this.transmitCoeffTE[i][j].abs();
2100 }
2101 }
2102
2103 String graphLegendExtra = " Absolute values of the TE transmission coefficients";
2104 String yLegend = "|TE Transmission Coefficient|";
2105 String yUnits = " ";
2106
2107 plotSimulation(legend, graphLegendExtra, yLegend, yUnits, (Object) absTEt);
2108 }
2109 }
2110
2111 // Calculation and plotting of the absolute values of TM transmission
2112 // coefficients for a single or multiple wavelengths and a range of incident
2113 // angles entered
2114 // No user legend provided
2115 public void plotAbsTMtransmissionCoefficients() {
2116 String legend = "Polarisation mode: " + this.mode;
2117 this.plotAbsTMtransmissionCoefficients(legend);
2118 }
2119
2120 // Calculation and plotting of the absolute values of TM transmission
2121 // coefficients for a single or multiple wavelengths and a range of incident
2122 // angles entered
2123 public void plotAbsTMtransmissionCoefficients(String legend) {
2124 this.checkWhichCalculation();
2125 if (this.singleReflectCalculated)
2126 throw new IllegalArgumentException("Plot methods require more than one data point");
2127
2128 if (tmFraction == 0.0D) {
2129 System.out.println("No TM transmission coefficient plot displayed as no light in the TM mode");
2130 } else {
2131 double[][] absTMt = new double[numberOfWavelengths][this.numberOfIncidentAngles];
2132 for (int i = 0; i < this.numberOfWavelengths; i++) {
2133 for (int j = 0; j < this.numberOfIncidentAngles; j++) {
2134 absTMt[i][j] = this.transmitCoeffTM[i][j].abs();
2135 }
2136 }
2137
2138 String graphLegendExtra = " Absolute values of the TM transmission coefficients";
2139 String yLegend = "|TM Transmission Coefficient|";
2140 String yUnits = " ";
2141
2142 plotSimulation(legend, graphLegendExtra, yLegend, yUnits, (Object) absTMt);
2143 }
2144 }
2145
2146 // Calculation and plotting of the integrated evanescent field for a single
2147 // or multiple wavelengths and a range of incident angles entered
2148 // No user legend provided
2149 public void plotEvanescentFields() {
2150 String legend = "Polarisation mode: " + this.mode;
2151 this.plotEvanescentFields(legend);
2152 }
2153
2154 // Calculation and plotting of the integrated evanescent field for a single
2155 // or multiple wavelengths and a range of incident angles entered
2156 // No user legend provided, resetting distnce over which field is integrated
2157 public void plotEvanescentFields(double distanceIntoField) {
2158 // this.fieldDistance = fieldDistance;
2159 String legend = "Polarisation mode: " + this.mode;
2160 this.plotEvanescentFields(legend);
2161 }
2162
2163 // Calculation and plotting of the integrated evanescent fields for a single
2164 // or multiple wavelengths and a range of incident angles entered
2165 // Resetting distnce over which field is integrated
2166 public void plotEvanescentFields(double fieldDistance, String legend) {
2167 this.fieldDistance = fieldDistance;
2168 this.plotEvanescentFields(legend);
2169 }
2170
2171 // Calculation and plotting of the integrated evanescent fields for a single
2172 // or multiple wavelengths and a range of incident angles entered
2173 public void plotEvanescentFields(String legend) {
2174 this.checkWhichCalculation();
2175 if (this.singleReflectCalculated)
2176 throw new IllegalArgumentException("Plot methods require more than one data point");
2177
2178 String graphLegendExtra = " Integrated Evanescent Field Intensities to a depth of " + this.fieldDistance
2179 + " metres";
2180 String yLegend = "Evanescent Field intensity";
2181 String yUnits = " ";
2182
2183 plotSimulation(legend, graphLegendExtra, yLegend, yUnits, (Object) this.evanescentFields);
2184 }
2185
2186 // Calculation and plotting of the evanescent field penetration depths for a
2187 // single or multiple wavelengths and a range of incident angles entered
2188 // No user legend provided
2189 public void plotPenetrationDepths() {
2190 String legend = "Polarisation mode: " + this.mode;
2191 this.plotPenetrationDepths(legend);
2192 }
2193
2194 // Calculation and plotting of the evanescent field penetration depths for a
2195 // single or multiple wavelengths and a range of incident angles entered
2196 public void plotPenetrationDepths(String graphLegend) {
2197 this.checkWhichCalculation();
2198 if (this.singleReflectCalculated)
2199 throw new IllegalArgumentException("Plot methods require more than one data point");
2200
2201 String graphLegendExtra = " Evanescent Field Penetration Depths";
2202 String yLegend = "Penetration Depth";
2203 String yUnits = "metres";
2204
2205 plotSimulation(graphLegend, graphLegendExtra, yLegend, yUnits, (Object) this.penetrationDepths);
2206 }
2207
2208 // Calculation and plotting of the phase shift on reflection (TE mode), in
2209 // degrees, for a single or multiple wavelengths and a range of incident
2210 // angles entered
2211 // No user legend provided
2212 public void plotTEreflectionPhaseShiftDeg() {
2213 String legend = "Polarisation mode: " + this.mode;
2214 this.plotTEreflectionPhaseShiftDeg(legend);
2215 }
2216
2217 // Calculation and plotting of the phase shift on reflection (TE mode), in
2218 // degrees, for a single or multiple wavelengths and a range of incident
2219 // angles entered
2220 public void plotTEreflectionPhaseShiftDeg(String legend) {
2221 this.checkWhichCalculation();
2222 if (this.singleReflectCalculated)
2223 throw new IllegalArgumentException("Plot methods require more than one data point");
2224
2225 if (teFraction == 0.0D) {
2226 System.out.println("No TE phase shift plot displayed as no light in the TE mode");
2227 } else {
2228 String graphLegendExtra = " Phase Shift on Reflection (TE mode)";
2229 String yLegend = "Phase shift";
2230 String yUnits = "degrees ";
2231 plotSimulation(legend, graphLegendExtra, yLegend, yUnits, (Object) this.reflectPhaseShiftDegTE);
2232 }
2233 }
2234
2235 // Calculation and plotting of the phase shift on reflection (TM mode), in
2236 // degrees, for a single or multiple wavelengths and a range of incident
2237 // angles entered
2238 // No user legend provided
2239 public void plotTMreflectionPhaseShiftDeg() {
2240 String legend = "Polarisation mode: " + this.mode;
2241 this.plotTMreflectionPhaseShiftDeg(legend);
2242 }
2243
2244 // Calculation and plotting of the phase shift on reflection (TM mode), in
2245 // degrees, for a single or multiple wavelengths and a range of incident
2246 // angles entered
2247 public void plotTMreflectionPhaseShiftDeg(String legend) {
2248 this.checkWhichCalculation();
2249 if (this.singleReflectCalculated)
2250 throw new IllegalArgumentException("Plot methods require more than one data point");
2251
2252 if (tmFraction == 0.0D) {
2253 System.out.println("No TM phase shift plot displayed as no light in the TM mode");
2254 } else {
2255 String graphLegendExtra = " Phase Shift on Reflection (TM mode)";
2256 String yLegend = "Phase shift";
2257 String yUnits = "degrees ";
2258 plotSimulation(legend, graphLegendExtra, yLegend, yUnits, (Object) this.reflectPhaseShiftDegTM);
2259 }
2260 }
2261
2262 // Calculation and plotting of the phase shift on reflection (TE mode), in
2263 // radians, for a single or multiple wavelengths and a range of incident
2264 // angles entered
2265 // No user legend provided
2266 public void plotTEreflectionPhaseShiftRad() {
2267 String legend = "Polarisation mode: " + this.mode;
2268 this.plotTEreflectionPhaseShiftRad(legend);
2269 }
2270
2271 // Calculation and plotting of the phase shift on reflection (TE mode), in
2272 // radians, for a single or multiple wavelengths and a range of incident
2273 // angles entered
2274 public void plotTEreflectionPhaseShiftRad(String legend) {
2275 this.checkWhichCalculation();
2276 if (this.singleReflectCalculated)
2277 throw new IllegalArgumentException("Plot methods require more than one data point");
2278
2279 if (teFraction == 0.0D) {
2280 System.out.println("No TE phase shift plot displayed as no light in the TE mode");
2281 } else {
2282 String graphLegendExtra = " Phase Shift on Reflection (TE mode)";
2283 String yLegend = "Phase shift";
2284 String yUnits = "radians ";
2285 plotSimulation(legend, graphLegendExtra, yLegend, yUnits, (Object) this.reflectPhaseShiftRadTE);
2286 }
2287 }
2288
2289 // Calculation and plotting of the phase shift on reflection (TM mode), in
2290 // radians, for a single or multiple wavelengths and a range of incident
2291 // angles entered
2292 // No user legend provided
2293 public void plotTMreflectionPhaseShiftRad() {
2294 String legend = "Polarisation mode: " + this.mode;
2295 this.plotTMreflectionPhaseShiftRad(legend);
2296 }
2297
2298 // Calculation and plotting of the phase shift on reflection (TM mode), in
2299 // radians, for a single or multiple wavelengths and a range of incident
2300 // angles entered
2301 public void plotTMreflectionPhaseShiftRad(String legend) {
2302 this.checkWhichCalculation();
2303 if (this.singleReflectCalculated)
2304 throw new IllegalArgumentException("Plot methods require more than one data point");
2305
2306 if (tmFraction == 0.0D) {
2307 System.out.println("No TM phase shift plot displayed as no light in the TM mode");
2308 } else {
2309 String graphLegendExtra = " Phase Shift on Reflection (TM mode)";
2310 String yLegend = "Phase shift";
2311 String yUnits = "radians ";
2312 plotSimulation(legend, graphLegendExtra, yLegend, yUnits, (Object) this.reflectPhaseShiftRadTM);
2313 }
2314 }
2315
2316 // Calculation and plotting of the phase shift on transmission (TE mode), in
2317 // degrees, for a single or multiple wavelengths and a range of incident
2318 // angles entered
2319 // No user legend provided
2320 public void plotTEtransmissionPhaseShiftDeg() {
2321 String legend = "Polarisation mode: " + this.mode;
2322 this.plotTEtransmissionPhaseShiftDeg(legend);
2323 }
2324
2325 // Calculation and plotting of the phase shift on transmission (TE mode), in
2326 // degrees, for a single or multiple wavelengths and a range of incident
2327 // angles entered
2328 public void plotTEtransmissionPhaseShiftDeg(String legend) {
2329 this.checkWhichCalculation();
2330 if (this.singleReflectCalculated)
2331 throw new IllegalArgumentException("Plot methods require more than one data point");
2332
2333 if (teFraction == 0.0D) {
2334 System.out.println("No TE phase shift plot displayed as no light in the TE mode");
2335 } else {
2336 String graphLegendExtra = " Phase Shift on Transmission (TE mode)";
2337 String yLegend = "Phase shift";
2338 String yUnits = "degrees ";
2339 plotSimulation(legend, graphLegendExtra, yLegend, yUnits, (Object) this.transmitPhaseShiftDegTE);
2340 }
2341 }
2342
2343 // Calculation and plotting of the phase shift on transmission (TM mode), in
2344 // degrees, for a single or multiple wavelengths and a range of incident
2345 // angles entered
2346 // No user legend provided
2347 public void plotTMtransmissionPhaseShiftDeg() {
2348 String legend = "Polarisation mode: " + this.mode;
2349 this.plotTMtransmissionPhaseShiftDeg(legend);
2350 }
2351
2352 // Calculation and plotting of the phase shift on transmission (TM mode), in
2353 // degrees, for a single or multiple wavelengths and a range of incident
2354 // angles entered
2355 public void plotTMtransmissionPhaseShiftDeg(String legend) {
2356 this.checkWhichCalculation();
2357 if (this.singleReflectCalculated)
2358 throw new IllegalArgumentException("Plot methods require more than one data point");
2359
2360 if (tmFraction == 0.0D) {
2361 System.out.println("No TM phase shift plot displayed as no light in the TM mode");
2362 } else {
2363 String graphLegendExtra = " Phase Shift on Transmission (TM mode)";
2364 String yLegend = "Phase shift";
2365 String yUnits = "degrees ";
2366 plotSimulation(legend, graphLegendExtra, yLegend, yUnits, (Object) this.transmitPhaseShiftDegTM);
2367 }
2368 }
2369
2370 // Calculation and plotting of the phase shift on transmission (TE mode), in
2371 // radians, for a single or multiple wavelengths and a range of incident
2372 // angles entered
2373 // No user legend provided
2374 public void plotTEtransmissionPhaseShiftRad() {
2375 String legend = "Polarisation mode: " + this.mode;
2376 this.plotTEtransmissionPhaseShiftRad(legend);
2377 }
2378
2379 // Calculation and plotting of the phase shift on transmission (TE mode), in
2380 // radians, for a single or multiple wavelengths and a range of incident
2381 // angles entered
2382 public void plotTEtransmissionPhaseShiftRad(String legend) {
2383 this.checkWhichCalculation();
2384 if (this.singleReflectCalculated)
2385 throw new IllegalArgumentException("Plot methods require more than one data point");
2386
2387 if (teFraction == 0.0D) {
2388 System.out.println("No TE phase shift plot displayed as no light in the TE mode");
2389 } else {
2390 String graphLegendExtra = " Phase Shift on Transmission (TE mode)";
2391 String yLegend = "Phase shift";
2392 String yUnits = "radians ";
2393 plotSimulation(legend, graphLegendExtra, yLegend, yUnits, (Object) this.transmitPhaseShiftRadTE);
2394 }
2395 }
2396
2397 // Calculation and plotting of the phase shift on transmission (TM mode), in
2398 // radians, for a single or multiple wavelengths and a range of incident
2399 // angles entered
2400 // No user legend provided
2401 public void plotTMtransmissionPhaseShiftRad() {
2402 String legend = "Polarisation mode: " + this.mode;
2403 this.plotTMtransmissionPhaseShiftRad(legend);
2404 }
2405
2406 // Calculation and plotting of the phase shift on transmission (TM mode), in
2407 // radians, for a single or multiple wavelengths and a range of incident
2408 // angles entered
2409 public void plotTMtransmissionPhaseShiftRad(String legend) {
2410 this.checkWhichCalculation();
2411 if (this.singleReflectCalculated)
2412 throw new IllegalArgumentException("Plot methods require more than one data point");
2413
2414 if (tmFraction == 0.0D) {
2415 System.out.println("No TM phase shift plot displayed as no light in the TM mode");
2416 } else {
2417 String graphLegendExtra = " Phase Shift on Transmission (TM mode)";
2418 String yLegend = "Phase shift";
2419 String yUnits = "radians ";
2420 plotSimulation(legend, graphLegendExtra, yLegend, yUnits, (Object) this.transmitPhaseShiftRadTM);
2421 }
2422 }
2423
2424 // Plotting of the simulation curves
2425 public void plotSimulation(String graphLegend, String graphLegendExtra, String yLegend, String yUnits,
2426 Object yValuesObject) {
2427
2428 // Calculate yValuesObject internal array dimensions and fill yValues
2429 // array
2430 Object internalArray = yValuesObject;
2431 int nCurves = 1;
2432 while (!((internalArray = Array.get(internalArray, 0)) instanceof Double))
2433 nCurves++;
2434 double[][] yValues = new double[nCurves][];
2435 if (nCurves == 1) {
2436 double[] temp = (double[]) yValuesObject;
2437 yValues[0] = temp;
2438 } else {
2439 yValues = (double[][]) yValuesObject;
2440 }
2441 int nPoints = yValues.length;
2442
2443 int[] pointOptions = null;
2444 double[][] plotData = null;
2445 String xLegend = null;
2446 String xUnits = null;
2447
2448 if (this.angularReflectCalculated) {
2449 pointOptions = new int[1];
2450 pointOptions[0] = 1;
2451 plotData = new double[2][nPoints];
2452 plotData[0] = this.incidentAngleDeg;
2453 plotData[1] = yValues[0];
2454 xLegend = "Incident Angle";
2455 xUnits = "degrees";
2456 }
2457
2458 if (this.wavelengthReflectCalculated) {
2459 pointOptions = new int[1];
2460 pointOptions[0] = 1;
2461 plotData = new double[2][nPoints];
2462 plotData[0] = this.wavelengths;
2463 double[] temp = new double[this.numberOfWavelengths];
2464 for (int i = 0; i < this.numberOfWavelengths; i++)
2465 temp[i] = yValues[i][0];
2466 switch (wavelengthAxisOption) {
2467 case 1:
2468 plotData[0] = this.wavelengths;
2469 plotData[1] = temp;
2470 xLegend = "Wavelength";
2471 xUnits = "metres";
2472 break;
2473 case 2:
2474 plotData[0] = this.frequencies;
2475 for (int i = 0; i < this.numberOfWavelengths; i++)
2476 plotData[1][this.numberOfWavelengths - 1 - i] = temp[i];
2477 xLegend = "Frequency";
2478 xUnits = "Hz";
2479 break;
2480 case 3:
2481 plotData[0] = this.omega;
2482 for (int i = 0; i < this.numberOfWavelengths; i++)
2483 plotData[1][this.numberOfWavelengths - 1 - i] = temp[i];
2484 xLegend = "Radial Frequency";
2485 xUnits = "radians";
2486 break;
2487 }
2488 }
2489
2490 if (this.wavelengthAndAngularReflectCalculated) {
2491 pointOptions = new int[nCurves];
2492 plotData = new double[2 * nCurves][nPoints];
2493 for (int i = 0; i < nCurves; i++) {
2494 pointOptions[i] = i + 1;
2495 plotData[2 * i] = this.incidentAngleDeg;
2496 plotData[2 * i + 1] = yValues[i];
2497 }
2498 xLegend = "Incident Angle";
2499 xUnits = "degrees";
2500 }
2501
2502 PlotGraph pg = new PlotGraph(plotData);
2503 pg.setGraphTitle("Class Reflectivity: Simulation Plot - " + graphLegendExtra);
2504 pg.setGraphTitle2(graphLegend);
2505 pg.setXaxisLegend(xLegend);
2506 pg.setYaxisLegend(yLegend);
2507 pg.setXaxisUnitsName(xUnits);
2508 if (!yUnits.equals(" "))
2509 pg.setYaxisUnitsName(yUnits);
2510 pg.setLine(3);
2511 pg.setPoint(pointOptions);
2512 pg.plot();
2513 }
2514
2515 // CORE CALCULATION METHODS
2516
2517 // Check whether reflectivity calculation has been performed
2518 // and perform calculation if not
2519 public void checkWhichCalculation() {
2520 boolean test = false;
2521 if (this.singleReflectCalculated)
2522 test = true;
2523 if (this.angularReflectCalculated)
2524 test = true;
2525 if (this.wavelengthReflectCalculated)
2526 test = true;
2527 if (this.wavelengthAndAngularReflectCalculated)
2528 test = true;
2529
2530 if (test) {
2531 if (this.fieldDistance != Double.POSITIVE_INFINITY && !this.fieldIntensityCalc) {
2532 int nkouter = this.numberOfLayers - 1;
2533 double integratedEvanescentField = 0.0D;
2534 for (int i = 0; i < this.numberOfWavelengths; i++) {
2535 for (int j = 0; j < this.numberOfIncidentAngles; j++) {
2536 if (this.kxVector[i][j][nkouter].getReal() == 0.0D) {
2537 double penetrationDepth = 1.0D / this.kxVector[i][j][nkouter].getImag();
2538 integratedEvanescentField += this.teFraction
2539 * Fmath.square(this.transmitCoeffTE[i][j].abs())
2540 * (1.0D - Math.exp(-2.0D * this.fieldDistance / penetrationDepth))
2541 * penetrationDepth / 2.0D;
2542 double refrTerm = this.refractiveIndices[i][0].getReal()
2543 / this.refractiveIndices[i][j].getReal();
2544 double magnTerm = Math.sqrt(this.relativeMagneticPermeabilities[i][nkouter].getReal()
2545 / this.relativeMagneticPermeabilities[i][0].getReal());
2546 integratedEvanescentField += this.teFraction
2547 * Fmath.square(this.transmitCoeffTM[i][j].abs()) * magnTerm * refrTerm
2548 * (1.0D - Math.exp(-2.0D * this.fieldDistance / penetrationDepth))
2549 * penetrationDepth / 2.0D;
2550 }
2551 }
2552 }
2553 this.fieldIntensityCalc = true;
2554 }
2555 } else {
2556 if (this.numberOfIncidentAngles == 0)
2557 throw new IllegalArgumentException("No incident angle/s has/have been entered");
2558 if (this.numberOfWavelengths == 0)
2559 throw new IllegalArgumentException("No wavelength/s has/have been entered");
2560
2561 if (this.numberOfWavelengths > 1)
2562 this.sortWavelengths();
2563
2564 // Calculate ko, k, kx and kz vectors
2565 // redundant arrays included for ease of programming
2566 this.koVector = Complex.threeDarray(this.numberOfWavelengths, this.numberOfIncidentAngles,
2567 this.numberOfLayers);
2568 this.kzVector = Complex.threeDarray(this.numberOfWavelengths, this.numberOfIncidentAngles,
2569 this.numberOfLayers);
2570 this.kVector = Complex.threeDarray(this.numberOfWavelengths, this.numberOfIncidentAngles,
2571 this.numberOfLayers);
2572 this.kxVector = Complex.threeDarray(this.numberOfWavelengths, this.numberOfIncidentAngles,
2573 this.numberOfLayers);
2574
2575 for (int i = 0; i < this.numberOfWavelengths; i++) {
2576 for (int j = 0; j < this.numberOfIncidentAngles; j++) {
2577 for (int k = 0; k < this.numberOfLayers; k++) {
2578 // Calculate ko values
2579 this.koVector[i][j][k].reset(2.0D * Math.PI / this.wavelengths[i], 0.0D);
2580
2581 // Calculate k vector
2582 this.kVector[i][j][k] = this.koVector[i][j][k].times(this.refractiveIndices[i][k])
2583 .times(Complex.sqrt(this.relativeMagneticPermeabilities[i][k]));
2584
2585 // Calculate kz vector
2586 this.kzVector[i][j][k] = this.koVector[i][j][k].times(this.refractiveIndices[i][0])
2587 .times(Complex.sqrt(this.relativeMagneticPermeabilities[i][0]));
2588 this.kzVector[i][j][k] = this.kzVector[i][j][k].times(Math.sin(this.incidentAngleRad[j]));
2589
2590 // Calculate kx vector
2591 this.kxVector[i][j][k] = (Complex.square(this.kVector[i][j][k]))
2592 .minus(Complex.square(this.kzVector[i][j][k]));
2593 this.kxVector[i][j][k] = Complex.sqrt(this.kxVector[i][j][k]);
2594 // if(this.kxVector[i][j][k].getImag()>0.0D)this.kxVector[i][j][k]
2595 // = this.kxVector[i][j][k].times(Complex.minusOne());
2596
2597 }
2598 }
2599 }
2600
2601 // Arrays for calculated parameters
2602 this.reflectivities = new double[this.numberOfWavelengths][this.numberOfIncidentAngles];
2603 this.transmissivities = new double[this.numberOfWavelengths][this.numberOfIncidentAngles];
2604 this.powerLosses = new double[this.numberOfWavelengths][this.numberOfIncidentAngles];
2605 this.reflectCoeffTE = Complex.twoDarray(this.numberOfWavelengths, this.numberOfIncidentAngles);
2606 this.reflectCoeffTM = Complex.twoDarray(this.numberOfWavelengths, this.numberOfIncidentAngles);
2607 this.transmitCoeffTE = Complex.twoDarray(this.numberOfWavelengths, this.numberOfIncidentAngles);
2608 this.transmitCoeffTM = Complex.twoDarray(this.numberOfWavelengths, this.numberOfIncidentAngles);
2609 this.evanescentFields = new double[this.numberOfWavelengths][this.numberOfIncidentAngles];
2610 this.penetrationDepths = new double[this.numberOfWavelengths][this.numberOfIncidentAngles];
2611 this.transmitAnglesRad = new double[this.numberOfWavelengths][this.numberOfIncidentAngles];
2612 this.transmitAnglesDeg = new double[this.numberOfWavelengths][this.numberOfIncidentAngles];
2613 this.reflectPhaseShiftRadTE = new double[this.numberOfWavelengths][this.numberOfIncidentAngles];
2614 this.reflectPhaseShiftRadTM = new double[this.numberOfWavelengths][this.numberOfIncidentAngles];
2615 this.reflectPhaseShiftDegTE = new double[this.numberOfWavelengths][this.numberOfIncidentAngles];
2616 this.reflectPhaseShiftDegTM = new double[this.numberOfWavelengths][this.numberOfIncidentAngles];
2617 this.transmitPhaseShiftRadTE = new double[this.numberOfWavelengths][this.numberOfIncidentAngles];
2618 this.transmitPhaseShiftRadTM = new double[this.numberOfWavelengths][this.numberOfIncidentAngles];
2619 this.transmitPhaseShiftDegTE = new double[this.numberOfWavelengths][this.numberOfIncidentAngles];
2620 this.transmitPhaseShiftDegTM = new double[this.numberOfWavelengths][this.numberOfIncidentAngles];
2621
2622 // Perform scan over angles and wavelengths
2623 this.scan();
2624 }
2625 }
2626
2627 // Calculation of the reflection coefficient for a single or multiple
2628 // wavelengths and a single or range of incident angles entered
2629 public void scan() {
2630 if (!this.wavelSet)
2631 throw new IllegalArgumentException("No wavelength has been entered");
2632 if (!this.refractSet)
2633 throw new IllegalArgumentException("No, or not all, refractive indices have been entered");
2634 if (!this.thickSet)
2635 throw new IllegalArgumentException("No, or not all, layer thicknesses have been entered");
2636 if (!this.incidentAngleSet)
2637 throw new IllegalArgumentException("No incident angle has been entered");
2638 if (!this.modeSet)
2639 throw new IllegalArgumentException(
2640 "No polaristaion mode (TE, TM, unpolarised or mixed[angle to be entered]) has been entered");
2641
2642 this.singleReflectCalculated = false;
2643 this.angularReflectCalculated = false;
2644 this.wavelengthReflectCalculated = false;
2645 this.wavelengthAndAngularReflectCalculated = false;
2646
2647 for (int i = 0; i < this.numberOfWavelengths; i++) {
2648 for (int j = 0; j < this.numberOfIncidentAngles; j++) {
2649 this.calcReflectivity(i, j);
2650 }
2651 }
2652
2653 if (this.numberOfWavelengths == 1) {
2654 if (this.numberOfIncidentAngles == 1) {
2655 this.singleReflectCalculated = true; // = true when only a
2656 // single angular
2657 // relectivity has been
2658 // calculated
2659 } else {
2660 this.angularReflectCalculated = true; // = true when an angular
2661 // relectivity scan has
2662 // been calculated
2663 }
2664 } else {
2665 if (this.numberOfIncidentAngles == 1) {
2666 this.wavelengthReflectCalculated = true; // = true when a
2667 // wavelength
2668 // relectivity scan
2669 // has been
2670 // calculated
2671 } else {
2672 this.wavelengthAndAngularReflectCalculated = true; // = true
2673 // when
2674 // angular
2675 // for each
2676 // wavelength
2677 // relectivity
2678 // scan has
2679 // been
2680 // calculated
2681 }
2682 }
2683 }
2684
2685 // Calculate the reflectivity at a given incident angle and wavelength
2686 public void calcReflectivity(int wavelengthIndex, int angleIndex) {
2687
2688 double[] ret1 = new double[6];
2689
2690 if (this.teFraction > 0.0D) {
2691 ret1 = this.calcTEreflectivity(wavelengthIndex, angleIndex);
2692 }
2693 if (this.tmFraction > 0.0D) {
2694 double[] ret2 = this.calcTMreflectivity(wavelengthIndex, angleIndex);
2695 ret1[0] = this.teFraction * ret1[0] + this.tmFraction * ret2[0];
2696 ret1[1] = this.teFraction * ret1[1] + this.tmFraction * ret2[1];
2697 ret1[2] = this.teFraction * ret1[2] + this.tmFraction * ret2[2];
2698 ret1[3] = this.teFraction * ret1[3] + this.tmFraction * ret2[3];
2699 ret1[4] = this.teFraction * ret1[4] + this.tmFraction * ret2[4];
2700 ret1[5] = this.teFraction * ret1[5] + this.tmFraction * ret2[5];
2701 }
2702
2703 this.reflectivities[wavelengthIndex][angleIndex] = ret1[0];
2704 this.transmissivities[wavelengthIndex][angleIndex] = ret1[1];
2705 this.transmitAnglesRad[wavelengthIndex][angleIndex] = ret1[2];
2706 this.transmitAnglesDeg[wavelengthIndex][angleIndex] = Math.toDegrees(ret1[2]);
2707 this.evanescentFields[wavelengthIndex][angleIndex] = ret1[3];
2708 this.penetrationDepths[wavelengthIndex][angleIndex] = ret1[4];
2709 this.powerLosses[wavelengthIndex][angleIndex] = ret1[5];
2710
2711 }
2712
2713 // Calculate the reflectivities for the TE mode
2714 public double[] calcTEreflectivity(int wavelengthIndex, int angleIndex) {
2715
2716 Complex tempc1 = Complex.zero(); // temporary variable for calculations
2717 Complex tempc2 = Complex.zero(); // temporary variable for calculations
2718 Complex tempc3 = Complex.zero(); // temporary variable for calculations
2719 Complex tempc4 = Complex.zero(); // temporary variable for calculations
2720
2721 double penetrationDepth = 0.0D;
2722
2723 if (this.numberOfLayers == 2) {
2724 tempc1 = this.relativeMagneticPermeabilities[wavelengthIndex][1]
2725 .times(this.kxVector[wavelengthIndex][angleIndex][0]);
2726 tempc2 = this.relativeMagneticPermeabilities[wavelengthIndex][0]
2727 .times(this.kxVector[wavelengthIndex][angleIndex][1]);
2728 tempc3 = tempc1.minus(tempc2);
2729 tempc4 = tempc1.plus(tempc2);
2730 this.reflectCoeffTE[wavelengthIndex][angleIndex] = tempc3.over(tempc4);
2731
2732 tempc3 = tempc1.times(2.0D);
2733 this.transmitCoeffTE[wavelengthIndex][angleIndex] = tempc3.over(tempc4);
2734 } else {
2735 // Create instance of Matrix Mi
2736 ComplexMatrix mati = new ComplexMatrix(2, 2);
2737
2738 // Create instance of Complex array Mi
2739 Complex[][] matic = Complex.twoDarray(2, 2);
2740
2741 // Calculate cos(theta[1]), beta[1], cos[beta[1]], sin[beta[1]],
2742 // p[1]
2743 Complex costheta = this.kxVector[wavelengthIndex][angleIndex][1]
2744 .over(this.kVector[wavelengthIndex][angleIndex][1]);
2745 Complex pTerm = (this.refractiveIndices[wavelengthIndex][1].over(this.impedance))
2746 .over(Complex.sqrt(this.relativeMagneticPermeabilities[wavelengthIndex][1]));
2747 pTerm = pTerm.times(costheta);
2748 Complex beta = this.kxVector[wavelengthIndex][angleIndex][1].times(this.thicknesses[1]);
2749 matic[0][0] = Complex.cos(beta);
2750 matic[1][1] = matic[0][0];
2751 tempc1 = Complex.sin(beta);
2752 tempc1 = tempc1.times(Complex.minusJay());
2753 matic[0][1] = tempc1.over(pTerm);
2754 matic[1][0] = tempc1.times(pTerm);
2755
2756 if (this.numberOfLayers > 3) {
2757
2758 // Create instance of Matrix M
2759 ComplexMatrix mat = new ComplexMatrix(Complex.copy(matic));
2760
2761 for (int i = 2; i < this.numberOfLayers - 1; i++) {
2762 costheta = this.kxVector[wavelengthIndex][angleIndex][i]
2763 .over(this.kVector[wavelengthIndex][angleIndex][i]);
2764 pTerm = (this.refractiveIndices[wavelengthIndex][i].over(this.impedance))
2765 .over(Complex.sqrt(this.relativeMagneticPermeabilities[wavelengthIndex][i]));
2766 pTerm = pTerm.times(costheta);
2767 beta = this.kxVector[wavelengthIndex][angleIndex][i].times(this.thicknesses[i]);
2768 matic[0][0] = Complex.cos(beta);
2769 matic[1][1] = matic[0][0];
2770 tempc1 = Complex.sin(beta);
2771 tempc1 = tempc1.times(Complex.minusJay());
2772 matic[0][1] = tempc1.over(pTerm);
2773 matic[1][0] = tempc1.times(pTerm);
2774 mati.setTwoDarray(Complex.copy(matic));
2775 mat = mat.times(mati);
2776 matic = mat.getArrayCopy();
2777 }
2778 }
2779
2780 costheta = this.kxVector[wavelengthIndex][angleIndex][0].over(this.kVector[wavelengthIndex][angleIndex][0]);
2781 Complex pTerm0 = (this.refractiveIndices[wavelengthIndex][0].over(this.impedance))
2782 .over(Complex.sqrt(this.relativeMagneticPermeabilities[wavelengthIndex][0]));
2783 pTerm0 = pTerm0.times(costheta);
2784
2785 costheta = this.kxVector[wavelengthIndex][angleIndex][this.numberOfLayers - 1]
2786 .over(this.kVector[wavelengthIndex][angleIndex][this.numberOfLayers - 1]);
2787 Complex pTermN = (this.refractiveIndices[wavelengthIndex][this.numberOfLayers - 1].over(this.impedance))
2788 .over(Complex.sqrt(this.relativeMagneticPermeabilities[wavelengthIndex][this.numberOfLayers - 1]));
2789 pTermN = pTermN.times(costheta);
2790
2791 tempc1 = matic[0][0].plus(matic[0][1].times(pTermN));
2792 tempc1 = tempc1.times(pTerm0);
2793 tempc2 = matic[1][0].plus(matic[1][1].times(pTermN));
2794 tempc3 = tempc1.minus(tempc2);
2795 tempc4 = tempc1.plus(tempc2);
2796 this.reflectCoeffTE[wavelengthIndex][angleIndex] = tempc3.over(tempc4);
2797 this.reflectPhaseShiftRadTE[wavelengthIndex][angleIndex] = this.reflectCoeffTE[wavelengthIndex][angleIndex]
2798 .arg();
2799 this.reflectPhaseShiftDegTE[wavelengthIndex][angleIndex] = Math
2800 .toDegrees(this.reflectPhaseShiftRadTE[wavelengthIndex][angleIndex]);
2801
2802 tempc3 = pTerm0.times(2.0D);
2803 this.transmitCoeffTE[wavelengthIndex][angleIndex] = tempc3.over(tempc4);
2804 this.transmitPhaseShiftRadTE[wavelengthIndex][angleIndex] = this.transmitCoeffTE[wavelengthIndex][angleIndex]
2805 .arg();
2806 this.transmitPhaseShiftDegTE[wavelengthIndex][angleIndex] = Math
2807 .toDegrees(this.transmitPhaseShiftRadTE[wavelengthIndex][angleIndex]);
2808 }
2809
2810 // Calculate and return reflectivity, transmissivity, transmitted angle,
2811 // evanescent field
2812 double reflectivity = Fmath.square(this.reflectCoeffTE[wavelengthIndex][angleIndex].getReal())
2813 + Fmath.square(this.reflectCoeffTE[wavelengthIndex][angleIndex].getImag());
2814
2815 int nkouter = this.numberOfLayers - 1;
2816 double tempd1 = Fmath.square(this.transmitCoeffTE[wavelengthIndex][angleIndex].getReal())
2817 + Fmath.square(this.transmitCoeffTE[wavelengthIndex][angleIndex].getImag());
2818 tempc2 = (this.relativeMagneticPermeabilities[wavelengthIndex][0]
2819 .over(this.relativeMagneticPermeabilities[wavelengthIndex][nkouter])).times(tempd1);
2820 tempc3 = this.kxVector[wavelengthIndex][angleIndex][nkouter].conjugate()
2821 .over(this.kxVector[wavelengthIndex][angleIndex][0]);
2822 Complex complexTransmissivity = tempc2.times(tempc3);
2823
2824 double transmissivity = 0.0D;
2825 double reflectedAngleRad = Math.PI / 2.0D;
2826 double integratedEvanescentField = 0.0D;
2827 if (this.kxVector[wavelengthIndex][angleIndex][nkouter].getReal() == 0.0D) {
2828 penetrationDepth = 1.0D / this.kxVector[wavelengthIndex][angleIndex][nkouter].getImag();
2829 integratedEvanescentField = Fmath.square(this.transmitCoeffTE[wavelengthIndex][angleIndex].abs())
2830 * (1.0D - Math.exp(-2.0D * this.fieldDistance / penetrationDepth)) * penetrationDepth / 2.0D;
2831 if (this.fieldDistance != Double.POSITIVE_INFINITY)
2832 this.fieldIntensityCalc = true;
2833 } else {
2834 transmissivity = complexTransmissivity.getReal();
2835 reflectedAngleRad = Math.atan2(this.kzVector[wavelengthIndex][angleIndex][nkouter].getReal(),
2836 this.kxVector[wavelengthIndex][angleIndex][nkouter].getReal());
2837 }
2838
2839 double powerLoss = 10.0D * Fmath.log10((1.0D - transmissivity) * 1e-3);
2840
2841 double[] ret = new double[6];
2842 ret[0] = reflectivity;
2843 ret[1] = transmissivity;
2844 ret[2] = reflectedAngleRad;
2845 ret[3] = integratedEvanescentField;
2846 ret[4] = penetrationDepth;
2847 ret[5] = powerLoss;
2848 return ret;
2849 }
2850
2851 // Calculate the reflectivities for the TM mode
2852 public double[] calcTMreflectivity(int wavelengthIndex, int angleIndex) {
2853
2854 Complex tempc1 = Complex.zero(); // temporary variable for calculations
2855 Complex tempc2 = Complex.zero(); // temporary variable for calculations
2856 Complex tempc3 = Complex.zero(); // temporary variable for calculations
2857 Complex tempc4 = Complex.zero(); // temporary variable for calculations
2858
2859 double penetrationDepth = 0.0D;
2860
2861 if (this.numberOfLayers == 2) {
2862 tempc1 = Complex.square(this.refractiveIndices[wavelengthIndex][1])
2863 .times(this.kxVector[wavelengthIndex][angleIndex][0]);
2864 tempc2 = Complex.square(this.refractiveIndices[wavelengthIndex][0])
2865 .times(this.kxVector[wavelengthIndex][angleIndex][1]);
2866 tempc3 = tempc1.minus(tempc2);
2867 tempc4 = tempc1.plus(tempc2);
2868 this.reflectCoeffTM[wavelengthIndex][angleIndex] = tempc3.over(tempc4);
2869
2870 tempc3 = tempc1.times(2.0D);
2871 this.transmitCoeffTM[wavelengthIndex][angleIndex] = tempc3.over(tempc4);
2872 } else {
2873 // Create instance of Matrix Mi
2874 ComplexMatrix mati = new ComplexMatrix(2, 2);
2875
2876 // Create instance of Complex array Mi
2877 Complex[][] matic = Complex.twoDarray(2, 2);
2878
2879 // Calculate cos(theta[1]), beta[1], cos[beta[1]], sin[beta[1]],
2880 // p[1]
2881 Complex costheta = this.kxVector[wavelengthIndex][angleIndex][1]
2882 .over(this.kVector[wavelengthIndex][angleIndex][1]);
2883 Complex pTerm = (this.refractiveIndices[wavelengthIndex][1].over(this.impedance))
2884 .over(Complex.sqrt(this.relativeMagneticPermeabilities[wavelengthIndex][1]));
2885 pTerm = pTerm.over(costheta);
2886 Complex beta = this.kxVector[wavelengthIndex][angleIndex][1].times(this.thicknesses[1]);
2887 matic[0][0] = Complex.cos(beta);
2888 matic[1][1] = matic[0][0];
2889 tempc1 = Complex.sin(beta);
2890 tempc1 = tempc1.times(Complex.minusJay());
2891 matic[0][1] = tempc1.over(pTerm);
2892 matic[1][0] = tempc1.times(pTerm);
2893
2894 if (this.numberOfLayers > 3) {
2895 // Create instance of Matrix M
2896 ComplexMatrix mat = new ComplexMatrix(Complex.copy(matic));
2897
2898 for (int i = 2; i < this.numberOfLayers - 1; i++) {
2899 costheta = this.kxVector[wavelengthIndex][angleIndex][i]
2900 .over(this.kVector[wavelengthIndex][angleIndex][i]);
2901 pTerm = (this.refractiveIndices[wavelengthIndex][i].over(this.impedance))
2902 .over(Complex.sqrt(this.relativeMagneticPermeabilities[wavelengthIndex][i]));
2903 pTerm = pTerm.over(costheta);
2904 beta = this.kxVector[wavelengthIndex][angleIndex][i].times(this.thicknesses[i]);
2905 matic[0][0] = Complex.cos(beta);
2906 matic[1][1] = matic[0][0];
2907 tempc1 = Complex.sin(beta);
2908 tempc1 = tempc1.times(Complex.minusJay());
2909 matic[0][1] = tempc1.over(pTerm);
2910 matic[1][0] = tempc1.times(pTerm);
2911 mati.setTwoDarray(Complex.copy(matic));
2912 mat = mat.times(mati);
2913 matic = mat.getArrayReference();
2914 }
2915 }
2916 costheta = this.kxVector[wavelengthIndex][angleIndex][0].over(this.kVector[wavelengthIndex][angleIndex][0]);
2917 Complex pTerm0 = (this.refractiveIndices[wavelengthIndex][0].over(this.impedance))
2918 .over(Complex.sqrt(this.relativeMagneticPermeabilities[wavelengthIndex][0]));
2919 pTerm0 = pTerm0.over(costheta);
2920
2921 costheta = this.kxVector[wavelengthIndex][angleIndex][this.numberOfLayers - 1]
2922 .over(this.kVector[wavelengthIndex][angleIndex][this.numberOfLayers - 1]);
2923 Complex pTermN = (this.refractiveIndices[wavelengthIndex][this.numberOfLayers - 1].over(this.impedance))
2924 .over(Complex.sqrt(this.relativeMagneticPermeabilities[wavelengthIndex][this.numberOfLayers - 1]));
2925 pTermN = pTermN.over(costheta);
2926
2927 tempc1 = matic[0][0].plus(matic[0][1].times(pTermN));
2928 tempc1 = tempc1.times(pTerm0);
2929 tempc2 = matic[1][0].plus(matic[1][1].times(pTermN));
2930 tempc3 = tempc1.minus(tempc2);
2931 tempc4 = tempc1.plus(tempc2);
2932 this.reflectCoeffTM[wavelengthIndex][angleIndex] = tempc3.over(tempc4);
2933 this.reflectPhaseShiftRadTM[wavelengthIndex][angleIndex] = this.reflectCoeffTM[wavelengthIndex][angleIndex]
2934 .arg();
2935 this.reflectPhaseShiftDegTM[wavelengthIndex][angleIndex] = Math
2936 .toDegrees(this.reflectPhaseShiftRadTM[wavelengthIndex][angleIndex]);
2937
2938 tempc3 = pTerm0.times(2.0D);
2939 this.transmitCoeffTM[wavelengthIndex][angleIndex] = tempc3.over(tempc4);
2940 this.transmitPhaseShiftRadTM[wavelengthIndex][angleIndex] = this.transmitCoeffTM[wavelengthIndex][angleIndex]
2941 .arg();
2942 this.transmitPhaseShiftDegTM[wavelengthIndex][angleIndex] = Math
2943 .toDegrees(this.transmitPhaseShiftRadTM[wavelengthIndex][angleIndex]);
2944 }
2945
2946 // Calculate and return reflectivity, transmissivity, transmitted angle,
2947 // evanescent field
2948 double reflectivity = Fmath.square(this.reflectCoeffTM[wavelengthIndex][angleIndex].getReal())
2949 + Fmath.square(this.reflectCoeffTM[wavelengthIndex][angleIndex].getImag());
2950
2951 int nkouter = this.numberOfLayers - 1;
2952 double tempd1 = Fmath.square(this.transmitCoeffTM[wavelengthIndex][angleIndex].getReal())
2953 + Fmath.square(this.transmitCoeffTM[wavelengthIndex][angleIndex].getImag());
2954 tempc2 = Complex.square(
2955 this.refractiveIndices[wavelengthIndex][0].over(this.refractiveIndices[wavelengthIndex][nkouter]))
2956 .times(tempd1);
2957 tempc3 = this.kxVector[wavelengthIndex][angleIndex][nkouter].conjugate()
2958 .over(this.kxVector[wavelengthIndex][angleIndex][0]);
2959 Complex complexTransmissivity = tempc2.times(tempc3);
2960
2961 double transmissivity = 0.0D;
2962 double reflectedAngleRad = Math.PI / 2.0D;
2963 double integratedEvanescentField = 0.0D;
2964 if (this.kxVector[wavelengthIndex][angleIndex][nkouter].getReal() == 0.0D) {
2965 penetrationDepth = 1.0D / this.kxVector[wavelengthIndex][angleIndex][nkouter].getImag();
2966 double refrTerm = this.refractiveIndices[wavelengthIndex][0].getReal()
2967 / this.refractiveIndices[wavelengthIndex][nkouter].getReal();
2968 double magnTerm = Math.sqrt(this.relativeMagneticPermeabilities[wavelengthIndex][nkouter].getReal()
2969 / this.relativeMagneticPermeabilities[wavelengthIndex][0].getReal());
2970 integratedEvanescentField = Fmath.square(this.transmitCoeffTM[wavelengthIndex][angleIndex].abs()) * magnTerm
2971 * refrTerm * (1.0D - Math.exp(-2.0D * this.fieldDistance / penetrationDepth)) * penetrationDepth
2972 / 2.0D;
2973 if (this.fieldDistance != Double.POSITIVE_INFINITY)
2974 this.fieldIntensityCalc = true;
2975 } else {
2976 transmissivity = complexTransmissivity.getReal();
2977 reflectedAngleRad = Math.atan2(this.kzVector[wavelengthIndex][angleIndex][nkouter].getReal(),
2978 this.kxVector[wavelengthIndex][angleIndex][nkouter].getReal());
2979 }
2980
2981 double powerLoss = 10.0D * Fmath.log10((1.0D - transmissivity) * 1e-3);
2982
2983 double[] ret = new double[6];
2984 ret[0] = reflectivity;
2985 ret[1] = transmissivity;
2986 ret[2] = reflectedAngleRad;
2987 ret[3] = integratedEvanescentField;
2988 ret[4] = penetrationDepth;
2989 ret[5] = powerLoss;
2990 return ret;
2991 }
2992
2993 // NON-LINEAR REGRESSION METHODS
2994
2995 // ENTER INDICES OF PARAMETERS TO BE ESTIMATED BY NON-LINEAR REGRESSION
2996
2997 // Enter indices of thicknesses to be estimated
2998 public void setThicknessEstimatesIndices(int[] indices) {
2999 this.thicknessEstimateIndices = indices;
3000 this.thicknessEstimateNumber = indices.length;
3001 }
3002
3003 // Enter indices of real parts of the refractive indices to be estimated
3004 public void setRealRefractIndexEstimateIndices(int[] indices) {
3005 this.refractIndexRealEstimateIndices = indices;
3006 this.refractIndexRealEstimateNumber = indices.length;
3007 }
3008
3009 // Enter indices of imaginary parts of the refractive indices to be
3010 // estimated
3011 public void setImagRefractIndexEstimateIndices(int[] indices) {
3012 this.refractIndexImagEstimateIndices = indices;
3013 this.refractIndexImagEstimateNumber = indices.length;
3014 this.refractIndexImagEstimateSet = true;
3015
3016 // Transfer absorption coefficient estimate indices to Imag[refractive
3017 // index] estimate indices list
3018 if (this.absorptionCoeffEstimateSet) {
3019 int[] temp0 = new int[this.absorptionCoeffEstimateNumber];
3020 int newIndex = 0;
3021 for (int i = 0; i < this.numberOfLayers; i++) {
3022 boolean testR = false;
3023 for (int j = 0; j < this.refractIndexImagEstimateNumber; j++) {
3024 if (i == this.refractIndexImagEstimateIndices[j])
3025 testR = true;
3026 }
3027 boolean testA = false;
3028 for (int j = 0; j < this.absorptionCoeffEstimateNumber; j++) {
3029 if (i == this.absorptionCoeffEstimateIndices[j])
3030 testA = true;
3031 }
3032 if (!testR && testA) {
3033 temp0[newIndex] = i;
3034 newIndex++;
3035 }
3036 }
3037 int newRefrNumber = this.refractIndexImagEstimateNumber + newIndex;
3038 int[] temp1 = new int[newRefrNumber];
3039 for (int j = 0; j < this.refractIndexImagEstimateNumber; j++) {
3040 temp1[j] = this.refractIndexImagEstimateIndices[j];
3041 }
3042 for (int j = 0; j < this.absorptionCoeffEstimateNumber; j++) {
3043 temp1[this.refractIndexImagEstimateNumber + j] = this.absorptionCoeffEstimateIndices[j];
3044 }
3045 this.refractIndexImagEstimateIndices = Fmath.selectionSort(temp1);
3046
3047 }
3048 }
3049
3050 // Enter indices of absorption coefficients to be estimated
3051 public void setAbsorptionCoefficientEstimateIndices(int[] indices) {
3052 this.absorptionCoeffEstimateIndices = indices;
3053 this.absorptionCoeffEstimateNumber = indices.length;
3054 this.absorptionCoeffEstimateSet = true;
3055
3056 // Transfer absorption coefficient estimate indices to Imag[refractive
3057 // index] estimate indices list
3058 if (this.refractIndexImagEstimateSet) {
3059 int[] temp0 = new int[this.absorptionCoeffEstimateNumber];
3060 int newIndex = 0;
3061 for (int i = 0; i < this.numberOfLayers; i++) {
3062 boolean testR = false;
3063 for (int j = 0; j < this.refractIndexImagEstimateNumber; j++) {
3064 if (i == this.refractIndexImagEstimateIndices[j])
3065 testR = true;
3066 }
3067 boolean testA = false;
3068 for (int j = 0; j < this.absorptionCoeffEstimateNumber; j++) {
3069 if (i == this.absorptionCoeffEstimateIndices[j])
3070 testA = true;
3071 }
3072 if (!testR && testA) {
3073 temp0[newIndex] = i;
3074 newIndex++;
3075 }
3076 }
3077 int newRefrNumber = this.refractIndexImagEstimateNumber + newIndex;
3078 int[] temp1 = new int[newRefrNumber];
3079 for (int j = 0; j < this.refractIndexImagEstimateNumber; j++) {
3080 temp1[j] = this.refractIndexImagEstimateIndices[j];
3081 }
3082 for (int j = 0; j < this.absorptionCoeffEstimateNumber; j++) {
3083 temp1[this.refractIndexImagEstimateNumber + j] = this.absorptionCoeffEstimateIndices[j];
3084 }
3085 this.refractIndexImagEstimateIndices = Fmath.selectionSort(temp1);
3086 } else {
3087 this.refractIndexImagEstimateIndices = this.absorptionCoeffEstimateIndices;
3088 this.refractIndexImagEstimateNumber = this.absorptionCoeffEstimateNumber;
3089 }
3090 }
3091
3092 // Enter indices of real parts of the relative magnetic permeabilities to be
3093 // estimated
3094 public void setRealRelativeMagneticPermeabilityEstimateIndices(int[] indices) {
3095 this.magneticPermRealEstimateIndices = indices;
3096 this.magneticPermRealEstimateNumber = indices.length;
3097 }
3098
3099 // Enter indices of imaginary parts of the relative magnetic permeabilities
3100 // to be estimated
3101 public void setImagRelativeMagneticPermeabilityEstimateIndices(int[] indices) {
3102 this.magneticPermImagEstimateIndices = indices;
3103 this.magneticPermImagEstimateNumber = indices.length;
3104 }
3105
3106 // FIT AND PLOT FIT - REFLECTIVITIES
3107
3108 // Fit reflectivities against incident angles
3109 // Errors (weights) not provided
3110 public void fitReflectivities(double[] experimentalReflectivities) {
3111 int n = experimentalReflectivities.length;
3112 double[] errors = new double[n];
3113 for (int i = 0; i < n; i++)
3114 errors[i] = 1.0D;
3115 fitReflectivities(experimentalReflectivities, errors);
3116 }
3117
3118 // Fit reflectivities against incident angles
3119 // Errors (weights) provided
3120 public void fitReflectivities(double[] experimentalReflectivities, double[] errors) {
3121 this.numberOfDataPoints = experimentalReflectivities.length;
3122 if (this.numberOfDataPoints != errors.length)
3123 throw new IllegalArgumentException("Number of data points, " + this.numberOfDataPoints
3124 + " is not equal to the number of errors (weights), " + errors.length + ".");
3125 if (this.incidentAngleSet) {
3126 if (this.numberOfDataPoints != this.numberOfIncidentAngles)
3127 throw new IllegalArgumentException("Number of experimental reflectivities " + this.numberOfDataPoints
3128 + " does not equal the number of incident angles " + this.numberOfIncidentAngles);
3129 double[] temp0 = Conv.copy(experimentalReflectivities);
3130 double[] temp1 = Conv.copy(errors);
3131 for (int i = 0; i < this.numberOfIncidentAngles; i++) {
3132 this.experimentalData[i] = temp0[this.incidentAngleIndices[i]];
3133 this.experimentalWeights[i] = temp1[this.incidentAngleIndices[i]];
3134 }
3135 }
3136 this.regressionOption = 1;
3137 this.experimentalDataSet = true;
3138
3139 this.nonLinearRegression();
3140 }
3141
3142 // Fit and plot reflectivities against incident angles
3143 // Errors (weights) not provided
3144 // Graph title not provided
3145 public void fitAndPlotReflectivities(double[] experimentalReflectivities) {
3146 fitReflectivities(experimentalReflectivities);
3147 String graphTitle = " ";
3148 plotFit(graphTitle);
3149 }
3150
3151 // Fit and plot reflectivities against incident angles
3152 // Errors (weights) not provided
3153 // Graph title provided
3154 public void fitAndPlotReflectivities(double[] experimentalReflectivities, String graphTitle) {
3155 fitReflectivities(experimentalReflectivities);
3156 plotFit(graphTitle);
3157 }
3158
3159 // Fit and plot reflectivities against incident angles
3160 // Errors (weights) provided
3161 // Graph title not provided
3162 public void fitAndPlotReflectivities(double[] experimentalReflectivities, double[] errors) {
3163 fitReflectivities(experimentalReflectivities, errors);
3164 String graphTitle = " ";
3165 plotFit(graphTitle);
3166 }
3167
3168 // Fit and plot reflectivities against incident angles
3169 // Errors (weights) provided
3170 // Graph title provided
3171 public void fitAndPlotReflectivities(double[] experimentalReflectivities, double[] errors, String graphTitle) {
3172 fitReflectivities(experimentalReflectivities, errors);
3173 plotFit(graphTitle);
3174 }
3175
3176 // FIT AND PLOT FIT - TRANSMISSIVITIES
3177
3178 // Fit transmissivities against incident angles
3179 // Errors (weights) not provided
3180 public void fitTransmissivities(double[] experimentalTransmissivities) {
3181 int n = experimentalTransmissivities.length;
3182 double[] errors = new double[n];
3183 for (int i = 0; i < n; i++)
3184 errors[i] = 1.0D;
3185 fitTransmissivities(experimentalTransmissivities, errors);
3186 }
3187
3188 // Fit transmissivities against incident angles
3189 // Errors (weights) provided
3190 public void fitTransmissivities(double[] experimentalTransmissivities, double[] errors) {
3191 this.numberOfDataPoints = experimentalTransmissivities.length;
3192 if (this.numberOfDataPoints != errors.length)
3193 throw new IllegalArgumentException("Number of data points, " + this.numberOfDataPoints
3194 + " is not equal to the number of errors (weights), " + errors.length + ".");
3195 if (this.incidentAngleSet) {
3196 if (this.numberOfDataPoints != this.numberOfIncidentAngles)
3197 throw new IllegalArgumentException("Number of experimental transmissivities " + this.numberOfDataPoints
3198 + " does not equal the number of incident angles " + this.numberOfIncidentAngles);
3199 double[] temp0 = Conv.copy(experimentalTransmissivities);
3200 double[] temp1 = Conv.copy(errors);
3201 for (int i = 0; i < this.numberOfIncidentAngles; i++) {
3202 this.experimentalData[i] = temp0[this.incidentAngleIndices[i]];
3203 this.experimentalWeights[i] = temp1[this.incidentAngleIndices[i]];
3204 }
3205 }
3206 this.regressionOption = 1;
3207 this.experimentalDataSet = true;
3208
3209 this.nonLinearRegression();
3210 }
3211
3212 // Fit and plot transmissivities against incident angles
3213 // Errors (weights) not provided
3214 // Graph title not provided
3215 public void fitAndPlotTransmissivities(double[] experimentalTransmissivities) {
3216 fitTransmissivities(experimentalTransmissivities);
3217 String graphTitle = " ";
3218 plotFit(graphTitle);
3219 }
3220
3221 // Fit and plot transmissivities against incident angles
3222 // Errors (weights) not provided
3223 // Graph title provided
3224 public void fitAndPlotTransmissivities(double[] experimentalTransmissivities, String graphTitle) {
3225 fitTransmissivities(experimentalTransmissivities);
3226 plotFit(graphTitle);
3227 }
3228
3229 // Fit and plot transmissivities against incident angles
3230 // Errors (weights) provided
3231 // Graph title not provided
3232 public void fitAndPlotTransmissivities(double[] experimentalTransmissivities, double[] errors) {
3233 fitTransmissivities(experimentalTransmissivities, errors);
3234 String graphTitle = " ";
3235 plotFit(graphTitle);
3236 }
3237
3238 // Fit and plot transmissivities against incident angles
3239 // Errors (weights) provided
3240 // Graph title provided
3241 public void fitAndPlotTransmissivities(double[] experimentalTransmissivities, double[] errors, String graphTitle) {
3242 fitTransmissivities(experimentalTransmissivities, errors);
3243 plotFit(graphTitle);
3244 }
3245
3246 // FIT AND PLOT FIT - EVANESCENT FIELDS
3247
3248 // Fit total evanescent field against incident angles
3249 // Errors (weights) not provided
3250 // Distance into field not provided
3251 public void fitEvanescentField(double[] experimentalEvanescentFieldIntensities) {
3252 int n = experimentalEvanescentFieldIntensities.length;
3253 double[] errors = new double[n];
3254 for (int i = 0; i < n; i++)
3255 errors[i] = 1.0D;
3256 double fieldDistance = Double.POSITIVE_INFINITY;
3257 fitEvanescentField(experimentalEvanescentFieldIntensities, errors, fieldDistance);
3258 }
3259
3260 // Fit total evanescent field against incident angles
3261 // Errors (weights) provided
3262 // Distance into field not provided
3263 public void fitEvanescentField(double[] experimentalEvanescentFieldIntensities, double[] errors) {
3264 double fieldDistance = Double.POSITIVE_INFINITY;
3265 this.fitEvanescentField(experimentalEvanescentFieldIntensities, errors, fieldDistance);
3266 }
3267
3268 // Fit total evanescent field against incident angles
3269 // Errors (weights) not provided
3270 // Distance into field provided
3271 public void fitEvanescentField(double[] experimentalEvanescentFieldIntensities, double fieldDistance) {
3272 int n = experimentalEvanescentFieldIntensities.length;
3273 double[] errors = new double[n];
3274 for (int i = 0; i < n; i++)
3275 errors[i] = 1.0D;
3276 fitEvanescentField(experimentalEvanescentFieldIntensities, errors, fieldDistance);
3277 }
3278
3279 // Fit evanescent field to a depth of fieldDistance against incident angles
3280 // Errors (weights) provided
3281 // Distance into field provided
3282 public void fitEvanescentField(double[] experimentalEvanescentFieldIntensities, double[] errors,
3283 double fieldDistance) {
3284 this.numberOfDataPoints = experimentalEvanescentFieldIntensities.length;
3285 if (this.numberOfDataPoints != errors.length)
3286 throw new IllegalArgumentException("Number of data points, " + this.numberOfDataPoints
3287 + " is not equal to the number of errors (weights), " + errors.length + ".");
3288
3289 if (this.incidentAngleSet) {
3290 if (this.numberOfDataPoints != this.numberOfIncidentAngles)
3291 throw new IllegalArgumentException("Number of experimental transmissivities " + this.numberOfDataPoints
3292 + " does not equal the number of incident angles " + this.numberOfIncidentAngles);
3293 double[] temp0 = Conv.copy(experimentalEvanescentFieldIntensities);
3294 double[] temp1 = Conv.copy(errors);
3295 for (int i = 0; i < this.numberOfIncidentAngles; i++) {
3296 this.experimentalData[i] = temp0[this.incidentAngleIndices[i]];
3297 this.experimentalWeights[i] = temp1[this.incidentAngleIndices[i]];
3298 }
3299 }
3300 this.regressionOption = 3;
3301 this.fieldDistance = fieldDistance;
3302 this.experimentalDataSet = true;
3303
3304 this.nonLinearRegression();
3305 }
3306
3307 // NELDER AND MEAD SIMPLEX NON-LINEAR REGRESSION
3308
3309 // Fit experimental data against incident angles
3310 public void nonLinearRegression() {
3311
3312 // Weighting option
3313 int ii = 0;
3314 boolean test = true;
3315 while (test) {
3316 if (this.experimentalWeights[ii] != 1.0D) {
3317 this.weightingOption = true;
3318 test = false;
3319 } else {
3320 ii++;
3321 if (ii >= this.numberOfDataPoints)
3322 test = false;
3323 }
3324 }
3325
3326 // Create an instance of Regression
3327 Regression regr = null;
3328 if (this.weightingOption) {
3329 regr = new Regression(this.incidentAngleDeg, this.experimentalData, this.experimentalWeights);
3330 } else {
3331 regr = new Regression(this.incidentAngleDeg, this.experimentalData);
3332 }
3333
3334 // Create instance of regression function
3335 RegressFunct funct0 = new RegressFunct();
3336
3337 // Transfer values to function
3338 funct0.numberOfLayers = this.numberOfLayers;
3339 funct0.mode = this.mode;
3340 funct0.eVectorAngleDeg = this.eVectorAngleDeg;
3341 funct0.thicknesses = this.thicknesses;
3342 funct0.refractiveIndices = this.refractiveIndices;
3343 funct0.relativeMagneticPermeabilities = this.relativeMagneticPermeabilities;
3344 funct0.regressionOption = this.regressionOption;
3345 funct0.thicknessEstimateIndices = this.thicknessEstimateIndices;
3346 funct0.refractIndexRealEstimateIndices = this.refractIndexRealEstimateIndices;
3347 funct0.refractIndexImagEstimateIndices = this.refractIndexImagEstimateIndices;
3348 funct0.magneticPermRealEstimateIndices = this.magneticPermRealEstimateIndices;
3349 funct0.magneticPermImagEstimateIndices = this.magneticPermImagEstimateIndices;
3350
3351 // Number of estimated parameters
3352 this.numberOfEstimatedParameters = this.thicknessEstimateNumber;
3353 this.numberOfEstimatedParameters += this.refractIndexRealEstimateNumber;
3354 this.numberOfEstimatedParameters += this.refractIndexImagEstimateNumber;
3355 this.numberOfEstimatedParameters += this.magneticPermRealEstimateNumber;
3356 this.numberOfEstimatedParameters += this.magneticPermImagEstimateNumber;
3357 if (this.regressionOption == 3)
3358 this.numberOfEstimatedParameters++;
3359
3360 this.degreesOfFreedom = this.numberOfDataPoints - this.numberOfEstimatedParameters;
3361 if (this.degreesOfFreedom < 1)
3362 throw new IllegalArgumentException("Number of parameters to be estimated, "
3363 + this.numberOfEstimatedParameters + ", is greater than or equal to the number of data points, "
3364 + this.numberOfDataPoints + ".");
3365
3366 // Fill initial estimate arrays
3367 double[] start = new double[this.numberOfEstimatedParameters];
3368 double[] init = new double[this.numberOfEstimatedParameters];
3369 double[] step = new double[this.numberOfEstimatedParameters];
3370
3371 int pIndex = 0;
3372 for (int i = 0; i < this.thicknessEstimateNumber; i++) {
3373 init[pIndex] = this.thicknesses[this.thicknessEstimateIndices[pIndex]];
3374 start[pIndex] = init[pIndex];
3375 step[pIndex] = init[pIndex] * 0.1D;
3376 if (step[pIndex] == 0.0D)
3377 step[pIndex] = 1e-9;
3378 pIndex++;
3379 }
3380 for (int i = 0; i < this.refractIndexRealEstimateNumber; i++) {
3381 init[pIndex] = this.refractiveIndices[0][this.refractIndexRealEstimateIndices[pIndex]].getReal();
3382 start[pIndex] = init[pIndex];
3383 step[pIndex] = init[pIndex] * 0.1D;
3384 if (step[pIndex] == 0.0D)
3385 step[pIndex] = 0.1D;
3386 pIndex++;
3387 }
3388 for (int i = 0; i < this.refractIndexImagEstimateNumber; i++) {
3389 init[pIndex] = this.refractiveIndices[0][this.refractIndexImagEstimateIndices[pIndex]].getImag();
3390 start[pIndex] = init[pIndex];
3391 step[pIndex] = init[pIndex] * 0.1D;
3392 if (step[pIndex] == 0.0D)
3393 step[pIndex] = 0.1D;
3394 pIndex++;
3395 }
3396 for (int i = 0; i < this.magneticPermRealEstimateNumber; i++) {
3397 init[pIndex] = this.relativeMagneticPermeabilities[0][this.magneticPermRealEstimateIndices[pIndex]]
3398 .getReal();
3399 start[pIndex] = init[pIndex];
3400 step[pIndex] = init[pIndex] * 0.1D;
3401 if (step[pIndex] == 0.0D)
3402 step[pIndex] = 0.1D;
3403 pIndex++;
3404 }
3405 for (int i = 0; i < this.magneticPermImagEstimateNumber; i++) {
3406 init[pIndex] = this.relativeMagneticPermeabilities[0][this.magneticPermImagEstimateIndices[pIndex]]
3407 .getImag();
3408 start[pIndex] = init[pIndex];
3409 step[pIndex] = init[pIndex] * 0.1D;
3410 if (step[pIndex] == 0.0D)
3411 step[pIndex] = 0.1D;
3412 pIndex++;
3413 }
3414
3415 // calculate scaling factor estimate if evanescent field fitting option
3416 // chosen
3417 if (this.regressionOption == 3) {
3418 double[] evanFields = (double[]) getEvanescentFields(this.fieldDistance);
3419 double calcFieldMean = 0.0D;
3420 double explFieldMean = 0.0D;
3421 for (int i = 0; i < this.numberOfDataPoints; i++) {
3422 if (evanFields[i] != 0.0D) {
3423 calcFieldMean += evanFields[i];
3424 explFieldMean += this.experimentalData[i];
3425 }
3426 }
3427 if (explFieldMean == 0.0D)
3428 throw new IllegalArgumentException("All entered field values are zero or sum to zero");
3429 if (calcFieldMean == 0.0D)
3430 throw new IllegalArgumentException("All calculated field values are zero or sum to zero");
3431 init[pIndex] = explFieldMean / calcFieldMean;
3432 start[pIndex] = init[pIndex];
3433 step[pIndex] = init[pIndex] * 0.1D;
3434 if (step[pIndex] == 0.0D)
3435 step[pIndex] = 0.1D;
3436 pIndex++;
3437 }
3438
3439 // Set tolerance for exiting regression
3440 double ftol = 1e-6;
3441
3442 // Set maximum iterations in regression
3443 int nmax = 1000;
3444
3445 // Call non-linear regression method
3446 regr.simplex(funct0, start, step, ftol, nmax);
3447
3448 // Get best estimates
3449 double[] bestEstimates = regr.getCoeff();
3450
3451 // Load best estimates into appropriate arrays
3452 pIndex = 0;
3453 for (int i = 0; i < this.thicknessEstimateNumber; i++) {
3454 this.thicknesses[this.thicknessEstimateIndices[pIndex]] = bestEstimates[pIndex];
3455 pIndex++;
3456 }
3457 for (int i = 0; i < this.refractIndexRealEstimateNumber; i++) {
3458 this.refractiveIndices[0][this.refractIndexRealEstimateIndices[pIndex]].setReal(bestEstimates[pIndex]);
3459 pIndex++;
3460 }
3461 for (int i = 0; i < this.refractIndexImagEstimateNumber; i++) {
3462 this.refractiveIndices[0][this.refractIndexImagEstimateIndices[pIndex]].setImag(bestEstimates[pIndex]);
3463 pIndex++;
3464 }
3465 for (int i = 0; i < this.magneticPermRealEstimateNumber; i++) {
3466 this.relativeMagneticPermeabilities[0][this.magneticPermRealEstimateIndices[pIndex]]
3467 .setReal(bestEstimates[pIndex]);
3468 pIndex++;
3469 }
3470 for (int i = 0; i < this.magneticPermImagEstimateNumber; i++) {
3471 this.relativeMagneticPermeabilities[0][this.magneticPermImagEstimateIndices[pIndex]]
3472 .setImag(bestEstimates[pIndex]);
3473 pIndex++;
3474 }
3475 if (this.regressionOption == 3)
3476 this.fieldScalingFactor = bestEstimates[pIndex];
3477
3478 // Get calculated data at best estimate values
3479 switch (this.regressionOption) {
3480 case 1: // transmissivity fitting
3481 this.calculatedData = (double[]) this.getReflectivities();
3482 break;
3483 case 2: // reflectivity fitting
3484 this.calculatedData = (double[]) this.getTransmissivities();
3485 break;
3486 case 3: // evanescent field fitting
3487 this.calculatedData = (double[]) this.getEvanescentFields();
3488 for (int i = 0; i < this.numberOfDataPoints; i++)
3489 this.calculatedData[i] *= this.fieldScalingFactor;
3490 break;
3491 default:
3492 throw new IllegalArgumentException("Regresion option " + regressionOption + " does not exist");
3493 }
3494 }
3495
3496 // Return calculated data
3497 public double[] getCalculatedData() {
3498 return this.calculatedData;
3499 }
3500
3501 // PLOT THE RESULTS OF THE NON-LINEAR REGRESSION
3502
3503 // Plot experimetal and calculated data
3504 public void plotFit(String graphTitle2) {
3505
3506 // Create data arrays to be plotted
3507 int numberOfCalculatedDataPoints = 200;
3508 double[][] data = PlotGraph.data(numberOfCalculatedDataPoints, 2);
3509
3510 // experimental data
3511 for (int i = 0; i < this.numberOfDataPoints; i++) {
3512 data[0][i] = this.incidentAngleDeg[i];
3513 data[1][i] = this.experimentalData[i];
3514 }
3515
3516 // calculated data
3517 double angleIncrement = (this.incidentAngleDeg[this.numberOfIncidentAngles - 1] - this.incidentAngleDeg[0])
3518 / (numberOfCalculatedDataPoints - 1);
3519 data[2][0] = this.incidentAngleDeg[0];
3520 for (int i = 1; i < numberOfCalculatedDataPoints - 1; i++)
3521 data[2][i] = data[2][i - 1] + angleIncrement;
3522 data[2][numberOfCalculatedDataPoints - 1] = this.incidentAngleDeg[this.numberOfIncidentAngles - 1];
3523
3524 // Create an instance of Reflectivity
3525 Reflectivity refl2 = new Reflectivity(this.numberOfLayers);
3526
3527 // Set mode
3528 if (this.mode.equals("mixed")) {
3529 refl2.setMode(eVectorAngleDeg);
3530 } else {
3531 refl2.setMode(this.mode);
3532 }
3533 // Set thicknesses to fixed values
3534 refl2.setThicknesses(this.thicknesses);
3535 // Set refractive index
3536 refl2.setRefractiveIndices(this.refractiveIndices);
3537 // Set relative magnetic permeability
3538 refl2.setRelativeMagneticPermeabilities(this.relativeMagneticPermeabilities);
3539 // Set incident angles
3540 refl2.setIncidentAngle(data[2]);
3541
3542 // Calculate values and plot legends
3543 String titleEnd = null;
3544 String yAxis = null;
3545 switch (regressionOption) {
3546 case 1: // transmissivity fitting
3547 data[3] = (double[]) refl2.getReflectivities();
3548 titleEnd = "Plot of reflectivities versus incident angle";
3549 yAxis = "Reflectivity";
3550 break;
3551 case 2: // reflectivity fitting
3552 data[3] = (double[]) refl2.getTransmissivities();
3553 titleEnd = "Plot of transmissivities versus incident angle";
3554 yAxis = "Transmissivity";
3555 break;
3556 case 3: // evanescent field fitting
3557 data[3] = (double[]) refl2.getEvanescentFields();
3558 for (int i = 0; i < numberOfCalculatedDataPoints; i++)
3559 data[3][i] *= this.fieldScalingFactor;
3560 titleEnd = "Plot of evanescent fields versus incident angle";
3561 yAxis = "Evanescent Field";
3562 break;
3563 default:
3564 throw new IllegalArgumentException("Regresion option " + regressionOption + " does not exist");
3565 }
3566
3567 // Create instance of PlotGraph
3568 PlotGraph pg = new PlotGraph(data);
3569
3570 pg.setGraphTitle("Reflectivity class: " + titleEnd);
3571 pg.setGraphTitle2(graphTitle2);
3572 pg.setXaxisLegend("Incident angle");
3573 pg.setXaxisUnitsName("degrees");
3574 pg.setYaxisLegend(yAxis);
3575
3576 int[] pointsOptions = { 1, 0 };
3577 pg.setPoint(pointsOptions);
3578
3579 int[] lineOptions = { 0, 3 };
3580 pg.setLine(lineOptions);
3581
3582 pg.plot();
3583 }
3584
3585}
3586
3587// REGRESSION FUNCTION CLASS
3588
3589// Class providing function for fitting reflectivities, transmissivities or
3590// evanescent fields over a range of angles
3591class RegressFunct implements RegressionFunction {
3592
3593 public int numberOfLayers = 0; // number of layers
3594 public String mode = null; // polarisation mode: TE, TM, unpolarised or
3595 // mixed
3596 public double eVectorAngleDeg = 0.0D; // the electric vector angle
3597 public double[] thicknesses = null; // the electric vector angle
3598 public double[] incidentAnglesDeg = null; // the incident angles
3599 public Complex[][] refractiveIndices = null; // refractive indices
3600 public Complex[][] relativeMagneticPermeabilities = null; // relative
3601 // magnetic
3602 // permeabilities
3603 public int regressionOption = 0; // Regression option
3604 // = 1; reflectivity versus angle
3605 // = 2; transmissivity versus angle
3606 // = 3; evanescent field versus angle
3607 public int[] thicknessEstimateIndices = null; // indices of the thicknesses
3608 // to be estimated by
3609 // non-linear regression
3610 public int[] refractIndexRealEstimateIndices = null; // indices of the
3611 // Real[refractive
3612 // indices] to be
3613 // estimated by
3614 // non-linear
3615 // regression
3616 public int[] refractIndexImagEstimateIndices = null; // indices of the
3617 // Imag[refractive
3618 // indices] to be
3619 // estimated by
3620 // non-linear
3621 // regression
3622 public int[] magneticPermRealEstimateIndices = null; // indices of the
3623 // Real[relative
3624 // magnetic
3625 // permeability] to
3626 // be estimated by
3627 // non-linear
3628 // regression
3629 public int[] magneticPermImagEstimateIndices = null; // indices of the
3630 // Imag[relative
3631 // magnetic
3632 // permeability] to
3633 // be estimated by
3634 // non-linear
3635 // regression
3636
3637 public double function(double[] p, double[] x) {
3638
3639 // Create instance oF Reflectivity for single angle calculation
3640 Reflectivity refl = new Reflectivity(this.numberOfLayers);
3641
3642 // set polarisation mode
3643 if (this.mode.equals("mixed")) {
3644 refl.setMode(eVectorAngleDeg);
3645 } else {
3646 refl.setMode(this.mode);
3647 }
3648
3649 // Add estimates of thicknesses to fixed values
3650 int pIndex = 0;
3651 int n = this.thicknessEstimateIndices.length;
3652 for (int i = 0; i < n; i++) {
3653 this.thicknesses[thicknessEstimateIndices[i]] = p[pIndex];
3654 pIndex++;
3655 }
3656 // Set thicknesses to fixed values
3657 refl.setThicknesses(this.thicknesses);
3658
3659 // Add estimates of Real[refractive index] to fixed values
3660 n = this.refractIndexRealEstimateIndices.length;
3661 for (int i = 0; i < n; i++) {
3662 this.refractiveIndices[0][this.refractIndexRealEstimateIndices[i]].setReal(p[pIndex]);
3663 pIndex++;
3664 }
3665
3666 // Add estimates of Imag[refractive index] to fixed values
3667 n = this.refractIndexImagEstimateIndices.length;
3668 for (int i = 0; i < n; i++) {
3669 this.refractiveIndices[0][this.refractIndexImagEstimateIndices[i]].setImag(p[pIndex]);
3670 pIndex++;
3671 }
3672
3673 // Set refractive index
3674 refl.setRefractiveIndices(this.refractiveIndices);
3675
3676 // Add estimates of Real[relative magnetic permeability] to fixed values
3677 n = this.magneticPermRealEstimateIndices.length;
3678 for (int i = 0; i < n; i++) {
3679 this.relativeMagneticPermeabilities[0][this.magneticPermRealEstimateIndices[i]].setReal(p[pIndex]);
3680 pIndex++;
3681 }
3682
3683 // Add estimates of Imag[relative magnetic permeability] to fixed values
3684 n = this.magneticPermImagEstimateIndices.length;
3685 for (int i = 0; i < n; i++) {
3686 this.relativeMagneticPermeabilities[0][this.magneticPermImagEstimateIndices[i]].setImag(p[pIndex]);
3687 pIndex++;
3688 }
3689
3690 // Set relative magnetic permeability
3691 refl.setRelativeMagneticPermeabilities(this.relativeMagneticPermeabilities);
3692
3693 // Set incident angle for this function calculation
3694 refl.setIncidentAngle(x[0]);
3695
3696 // Calculate value returned by this function
3697 double returnValue = 0.0;
3698 switch (regressionOption) {
3699 case 1: // transmissivity fitting
3700 returnValue = ((double[]) refl.getReflectivities())[0];
3701 break;
3702 case 2: // reflectivity fitting
3703 returnValue = ((double[]) refl.getTransmissivities())[0];
3704 break;
3705 case 3: // evanescent field fitting
3706 returnValue = p[pIndex] * ((double[]) refl.getEvanescentFields())[0];
3707 break;
3708 default:
3709 throw new IllegalArgumentException("Regresion option " + regressionOption + " does not exist");
3710 }
3711
3712 return returnValue;
3713
3714 }
3715}
Note: See TracBrowser for help on using the repository browser.