source: src/main/java/agents/anac/y2015/agentBuyogV2/flanagan/optics/PlanarWaveguide.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: 88.7 KB
Line 
1/*
2* PlanarWaveguide Class
3*
4* Methods for:
5* determining the refractive index of a waveguiding thin film
6* in an asymmetric slab waveguide from the effective refractive index, i.e.
7* the normalised propagation vector, and the core layer thickness
8*
9* determinimg the refractive index of the superstrate [waveguide coupler sensor]
10*
11* obtaining the normalised propagation vector versus guiding layer thickness
12* dispersion curve for an asymmetric slab waveguide
13*
14*
15* This is the superclass for the subclasses PrismCoupler and GratingCoupler
16*
17* Author: Dr Michael Thomas Flanagan.
18*
19* Created: March 2006
20* Revised: 29 April 2006, 5-7 July 2008, 9 November 2009
21*
22* DOCUMENTATION:
23* See Michael Thomas Flanagan's Java library on-line web page:
24* http://www.ee.ucl.ac.uk/~mflanaga/java/PlanarWaveguide.html
25* http://www.ee.ucl.ac.uk/~mflanaga/java/
26*
27* Copyright (c) 2006 - 2009 Michael Thomas Flanagan
28*
29* PERMISSION TO COPY:
30*
31* Permission to use, copy and modify this software and its documentation for NON-COMMERCIAL purposes is granted, without fee,
32* provided that an acknowledgement to the author, Dr Michael Thomas Flanagan at www.ee.ucl.ac.uk/~mflanaga, appears in all copies
33* and associated documentation or publications.
34*
35* Redistributions of the source code of this source code, or parts of the source codes, must retain the above copyright notice, this list of conditions
36* and the following disclaimer and requires written permission from the Michael Thomas Flanagan:
37*
38* Redistribution in binary form of all or parts of this class must reproduce the above copyright notice, this list of conditions and
39* the following disclaimer in the documentation and/or other materials provided with the distribution and requires written permission from the Michael Thomas Flanagan:
40*
41* Dr Michael Thomas Flanagan makes no representations about the suitability or fitness of the software for any or for a particular purpose.
42* Dr Michael Thomas Flanagan shall not be liable for any damages suffered as a result of using, modifying or distributing this software
43* or its derivatives.
44*
45***************************************************************************************/
46
47 package agents.anac.y2015.agentBuyogV2.flanagan.optics;
48
49import java.util.ArrayList;
50
51import agents.anac.y2015.agentBuyogV2.flanagan.analysis.Stat;
52import agents.anac.y2015.agentBuyogV2.flanagan.math.*;
53import agents.anac.y2015.agentBuyogV2.flanagan.optics.RefractiveIndex;
54import agents.anac.y2015.agentBuyogV2.flanagan.plot.*;
55import agents.anac.y2015.agentBuyogV2.flanagan.roots.*;
56
57public class PlanarWaveguide{
58
59 // CLASS VARIABLES
60
61 protected double[][] measurementsTE = null; // experimental TE mode measurements
62 // [film thickness][effective refractive index][weight][mode number]
63 protected int numberOfTEmeasurements = 0; // number of TE mode experimental measurements
64 protected double[] thicknessesUsedTE = null; // TE mode thicknesses used in calculation
65 protected double[] calcEffectRefrIndicesTE = null; // TE mode calculated effective refractive indices for mean core refractive index
66 protected boolean setMeasurementsTE = false; // = true when TE mode measurements entered
67 protected boolean setErrorsTE = false; // = true when TE mode errors entered
68 protected double maximumTEmodeEffectiveRefractiveIndex = 0.0D; // Maximum TE mode effective refractive index value
69 protected double minimumTEmodeEffectiveRefractiveIndex = 0.0D; // Minimum TE mode effective refractive index value
70 protected double[][] measurementsTM = null; // experimental TM mode measurements
71 // [film thickness][effective refractive index][weight][mode number]
72 protected int numberOfTMmeasurements = 0; // number of TM mode experimental measurements
73 protected double[] thicknessesUsedTM = null; // TM mode thicknesses used in calculation
74 protected double[] calcEffectRefrIndicesTM = null; // TM mode calculated effective refractive indices for mean core refractive index
75 protected boolean setMeasurementsTM = false; // = true when TM mode measurements entered
76 protected boolean setErrorsTM = false; // = true when TM mode errors entered
77 protected double maximumTMmodeEffectiveRefractiveIndex = 0.0D; // Maximum TM mode effective refractive index value
78 protected double minimumTMmodeEffectiveRefractiveIndex = 0.0D; // Minimum TM mode effective refractive index value
79 protected double maximumEffectiveRefractiveIndex = 0.0D; // Maximum overall effective refractive index value
80 protected double minimumEffectiveRefractiveIndex = 0.0D; // Minimum overall effective refractive index value
81 protected int numberOfMeasurements = 0; // total number of experimental measurements
82 protected boolean setMeasurements = false; // = true when measurements entered
83 protected boolean setWeights = false; // = true when weights entered
84 protected boolean[] eliminatedTE = null; // = true when TE point eliminated if effective refractive index lies below physical limit (Max[sub or superstrate]
85 protected boolean[] eliminatedTM = null; // = true when TM point eliminated if effective refractive index lies below physical limit (Max[sub or superstrate]
86 protected double wavelength = 0; // wavelength of the exciting light
87 protected boolean setWavelength= false; // = true when wavelength entered
88 protected double ko = 0.0D; // wave vector, 2pi/lambda
89
90 protected double superstrateRefractiveIndex = 0.0D; // superstrate refractive index
91 // default value: air
92 protected double superstrateRefractiveIndex2 = 0.0D;// superstrate refractive index squared
93 protected double[] calcSuperstrateTEmodeRI = null; // calculated TE mode superstrate refractive index values
94 protected double[] calcSuperstrateTMmodeRI = null; // calculated TM mode superstrate refractive index values
95 protected double meanTEmodeSuperstrateRefractiveIndex = Double.NaN; // mean of the TE mode superstrate refractive indices
96 protected double meanTMmodeSuperstrateRefractiveIndex = Double.NaN; // mean of the TM mode superstrate refractive indices
97
98 protected double sdTEmodeSuperstrateRefractiveIndex = Double.NaN; // standard deviation of the TE mode superstrate refractive indices
99 protected double sdTMmodeSuperstrateRefractiveIndex = Double.NaN; // standard deviation of the TM mode superstrate refractive indices
100 protected double sdSuperstrateRefractiveIndex = Double.NaN; // standard deviation of the superstrate refractive indices
101 protected boolean setSuperstrate = false; // = true when superstrate refractive index entered
102 protected boolean superCalculationDone = false; // = true when superstrate refractive index has been calculated
103
104 protected double substrateRefractiveIndex = 0.0D; // substrate refractive index
105 protected double substrateRefractiveIndex2 = 0.0D; // substrate refractive index squared
106 protected boolean setSubstrate = false; // = true when substrate refractive index entered
107 protected double coreFilmRefractiveIndex = 0.0D; // guiding layer thin film refractive index
108 protected double coreFilmRefractiveIndex2 = 0.0D; // guiding layer thin film refractive index squared
109 protected boolean setCore = false; // = true when guiding layer refractive index entered or calculated
110 protected double[] coreFilmTEmodeRefractiveIndices = null; // core film TE mode refractive indices
111 protected double[] coreFilmTMmodeRefractiveIndices = null; // core film TM mode refractive indices
112 protected double meanTEmodeCoreFilmRefractiveIndex = Double.NaN; // mean of the TE mode core film refractive indices
113 protected double meanTMmodeCoreFilmRefractiveIndex = Double.NaN; // mean of the TM mode core film refractive indices
114 protected double meanCoreFilmRefractiveIndex = Double.NaN; // mean of the TE and TM mode core film refractive indices
115 protected double meanCoreFilmRefractiveIndex2 = Double.NaN; // square of the mean of the TE and TM mode core film refractive indices
116 protected double sdTEmodeCoreFilmRefractiveIndex = Double.NaN; // standard deviation of the TE mode core film refractive indices
117 protected double sdTMmodeCoreFilmRefractiveIndex = Double.NaN; // standard deviation of the TM mode core film refractive indices
118 protected double sdCoreFilmRefractiveIndex = Double.NaN; // standard deviation of the TE and TM mode core film refractive indices
119 protected double lowerBound = 0.0D; // lower bound in a root search
120 protected double upperBound = 0.0D; // upper bound in a root search
121 protected double tolerance = 1e-9; // root search tolerance
122 protected boolean calculationDone = false; // = true when calculation of core film refractive index/indices completed
123
124 protected double prismToWaveguideGap = Double.POSITIVE_INFINITY; // prism to waveguide gap (subclass PrismCoupler)
125 protected boolean setPrismToWaveguideGap = false; // = true when prism to waveguide gap set (subclass PrismCoupler)
126 protected boolean fixedPrismToWaveguideGap = true; // = true when prism to waveguide gap set at a fixed value (subclass PrismCoupler)
127 // = false when prism to waveguide gap is to be estimated (subclass PrismCoupler)
128 protected double prismRefractiveIndex = 0.0D; // substrate refractive index
129 protected double prismRefractiveIndex2 = 0.0D; // substrate refractive index squared
130
131
132 // CONSTRUCTOR
133 public PlanarWaveguide(){
134 }
135
136 // THICKNESS (metres), EFFECTIVE REFRACTIVE INDEX AND MODE NUMBER DATA
137 // Enter TE mode data for a single measurement with no weights
138 public void enterTEmodeData(double thickness, double effectiveRI, double modeNumber){
139 if(setMeasurementsTE){
140 if(setErrorsTE)throw new IllegalArgumentException("All Entered data must either all have associated errors entered or all have no associated errors entered");
141 int nNew = this.numberOfTEmeasurements + 1;
142 double[][] hold = new double[nNew][4];
143 for(int i=0; i<this.numberOfTEmeasurements; i++){
144 for(int j=0; j<4; j++)hold[i][j] = this.measurementsTE[i][j];
145 }
146 hold[this.numberOfTEmeasurements][0] = thickness;
147 hold[this.numberOfTEmeasurements][1] = effectiveRI;
148 hold[this.numberOfTEmeasurements][2] = 1.0D;
149 hold[this.numberOfTEmeasurements][3] = modeNumber;
150 this.measurementsTE = hold;
151 this.numberOfTEmeasurements = nNew;
152 }
153 else{
154 this.measurementsTE = new double[1][4];
155 this.measurementsTE[0][0] = thickness;
156 this.measurementsTE[0][1] = effectiveRI;
157 this.measurementsTE[0][2] = 1.0D;
158 this.measurementsTE[0][3] = modeNumber;
159 this.numberOfTEmeasurements = 1;
160 }
161 this.numberOfMeasurements = this.numberOfTEmeasurements + this.numberOfTMmeasurements;
162 this.setMeasurementsTE = true;
163 this.setMeasurements = true;
164 }
165
166 // Enter TE mode data for a single measurement with weights
167 public void enterTEmodeData(double thickness, double effectiveRI, double weight, double modeNumber){
168 if(setMeasurementsTE){
169 if(!setErrorsTE)throw new IllegalArgumentException("All Entered data must either all have associated errors entered or all have no associated errors entered");
170 int nNew = this.numberOfTEmeasurements + 1;
171 double[][] hold = new double[nNew][4];
172 for(int i=0; i<this.numberOfTEmeasurements; i++){
173 for(int j=0; j<4; j++)hold[i][j] = this.measurementsTE[i][j];
174 }
175 hold[this.numberOfTEmeasurements][0] = thickness;
176 hold[this.numberOfTEmeasurements][1] = effectiveRI;
177 hold[this.numberOfTEmeasurements][2] = weight;
178 hold[this.numberOfTEmeasurements][3] = modeNumber;
179 this.measurementsTE = hold;
180 this.numberOfTEmeasurements = nNew;
181 }
182 else{
183 this.measurementsTE = new double[1][4];
184 this.measurementsTE[0][0] = thickness;
185 this.measurementsTE[0][1] = effectiveRI;
186 this.measurementsTE[0][2] = weight;
187 this.measurementsTE[0][3] = modeNumber;
188 this.numberOfTEmeasurements = 1;
189 }
190 this.numberOfMeasurements = this.numberOfTEmeasurements + this.numberOfTMmeasurements;
191 this.setMeasurementsTE = true;
192 this.setMeasurements = true;
193 this.setErrorsTE = true;
194 }
195
196 // Enter TE mode data for a range of measurements with no weights
197 public void enterTEmodeData(double[]thicknesses, double[] effectiveRIs, double[] modeNumbers){
198 int o = thicknesses.length;
199 int n = effectiveRIs.length;
200 if(n!=o)throw new IllegalArgumentException("number of thicknesses, " + o + ", does not equal the number of effective refractive indices, " + n);
201 int m = modeNumbers.length;
202 if(m!=o)throw new IllegalArgumentException("number of thicknesses, " + o + ", does not equal the number of mode numbers, " + m);
203
204 if(setMeasurementsTE){
205 if(setErrorsTE)throw new IllegalArgumentException("All Entered data must either all have associated errors entered or all have no associated errors entered");
206 int nNew = this.numberOfTEmeasurements + o;
207 double[][] hold = new double[nNew][4];
208 for(int i=0; i<this.numberOfTEmeasurements; i++){
209 for(int j=0; j<4; j++)hold[i][j] = this.measurementsTE[i][j];
210 }
211 for(int i=0; i<o; i++){
212 hold[this.numberOfTEmeasurements + i][0] = thicknesses[i];
213 hold[this.numberOfTEmeasurements + i][1] = effectiveRIs[i];
214 hold[this.numberOfTEmeasurements + i][2] = 1.0D;
215 hold[this.numberOfTEmeasurements + i][3] = modeNumbers[i];
216 }
217 this.measurementsTE = hold;
218 this.numberOfTEmeasurements = nNew;
219 }
220 else{
221 this.numberOfTEmeasurements = o;
222 this.measurementsTE = new double[this.numberOfTEmeasurements][4];
223 for(int i=0; i<this.numberOfTEmeasurements; i++){
224 this.measurementsTE[i][0] = thicknesses[i];
225 this.measurementsTE[i][1] = effectiveRIs[i];
226 this.measurementsTE[i][2] = 1.0D;
227 this.measurementsTE[i][3] = modeNumbers[i];
228 }
229
230 }
231 this.numberOfMeasurements = this.numberOfTEmeasurements + this.numberOfTMmeasurements;
232 this.setMeasurementsTE = true;
233 this.setMeasurements = true;
234 }
235
236 // Enter TE mode data for a range of measurements with weights
237 public void enterTEmodeData(double[]thicknesses, double[] effectiveRIs, double[] weights, double[] modeNumbers){
238 int o = thicknesses.length;
239 int n = effectiveRIs.length;
240 if(n!=o)throw new IllegalArgumentException("number of thicknesses, " + o + ", does not equal the number of effective refractive indices, " + n);
241 int m = modeNumbers.length;
242 if(m!=o)throw new IllegalArgumentException("number of thicknesses, " + o + ", does not equal the number of mode numbers, " + m);
243
244 if(setMeasurementsTE){
245 if(!setErrorsTE)throw new IllegalArgumentException("All Entered data must either all have associated errors entered or all have no associated errors entered");
246 int nNew = this.numberOfTEmeasurements + o;
247 double[][] hold = new double[nNew][4];
248 for(int i=0; i<this.numberOfTEmeasurements; i++){
249 for(int j=0; j<4; j++)hold[i][j] = this.measurementsTE[i][j];
250 }
251 for(int i=0; i<o; i++){
252 hold[this.numberOfTEmeasurements + i][0] = thicknesses[i];
253 hold[this.numberOfTEmeasurements + i][1] = effectiveRIs[i];
254 hold[this.numberOfTEmeasurements + i][2] = weights[i];
255 hold[this.numberOfTEmeasurements + i][3] = modeNumbers[i];
256 }
257 this.measurementsTE = hold;
258 this.numberOfTEmeasurements = nNew;
259 }
260 else{
261 this.numberOfTEmeasurements = o;
262 this.measurementsTE = new double[this.numberOfTEmeasurements][4];
263 for(int i=0; i<this.numberOfTEmeasurements; i++){
264 this.measurementsTE[i][0] = thicknesses[i];
265 this.measurementsTE[i][1] = effectiveRIs[i];
266 this.measurementsTE[i][2] = weights[i];
267 this.measurementsTE[i][3] = modeNumbers[i];
268 }
269 }
270 this.numberOfMeasurements = this.numberOfTEmeasurements + this.numberOfTMmeasurements;
271 this.setMeasurementsTE = true;
272 this.setMeasurements = true;
273 this.setErrorsTE = true;
274 }
275
276
277
278 // Enter TM mode data for a single measurement with no weights
279 public void enterTMmodeData(double thickness, double effectiveRI, double modeNumber){
280 if(setMeasurementsTM){
281 if(setErrorsTM)throw new IllegalArgumentException("All Entered data must either all have associated errors entered or all have no associated errors entered");
282 int nNew = this.numberOfTMmeasurements + 1;
283 double[][] hold = new double[nNew][4];
284 for(int i=0; i<this.numberOfTMmeasurements; i++){
285 for(int j=0; j<4; j++)hold[i][j] = this.measurementsTM[i][j];
286 }
287 hold[this.numberOfTMmeasurements][0] = thickness;
288 hold[this.numberOfTMmeasurements][1] = effectiveRI;
289 hold[this.numberOfTMmeasurements][2] = 1.0D;
290 hold[this.numberOfTMmeasurements][3] = modeNumber;
291 this.measurementsTM = hold;
292 this.numberOfTMmeasurements = nNew;
293 }
294 else{
295 this.measurementsTM = new double[1][4];
296 this.measurementsTM[0][0] = thickness;
297 this.measurementsTM[0][1] = effectiveRI;
298 this.measurementsTM[0][2] = 1.0D;
299 this.measurementsTM[0][3] = modeNumber;
300 this.numberOfTMmeasurements = 1;
301 }
302 this.numberOfMeasurements = this.numberOfTEmeasurements + this.numberOfTMmeasurements;
303 this.setMeasurementsTM = true;
304 this.setMeasurements = true;
305 }
306
307 // Enter TM mode data for a single measurement with weights
308 public void enterTMmodeData(double thickness, double effectiveRI, double weight, double modeNumber){
309 if(setMeasurementsTM){
310 if(!setErrorsTM)throw new IllegalArgumentException("All Entered data must either all have associated errors entered or all have no associated errors entered");
311 int nNew = this.numberOfTMmeasurements + 1;
312 double[][] hold = new double[nNew][4];
313 for(int i=0; i<this.numberOfTMmeasurements; i++){
314 for(int j=0; j<4; j++)hold[i][j] = this.measurementsTM[i][j];
315 }
316 hold[this.numberOfTMmeasurements][0] = thickness;
317 hold[this.numberOfTMmeasurements][1] = effectiveRI;
318 hold[this.numberOfTMmeasurements][2] = weight;
319 hold[this.numberOfTMmeasurements][3] = modeNumber;
320 this.measurementsTM = hold;
321 this.numberOfTMmeasurements = nNew;
322 }
323 else{
324 this.measurementsTM = new double[1][4];
325 this.measurementsTM[0][0] = thickness;
326 this.measurementsTM[0][1] = effectiveRI;
327 this.measurementsTM[0][2] = weight;
328 this.measurementsTM[0][3] = modeNumber;
329 this.numberOfTMmeasurements = 1;
330 }
331 this.numberOfMeasurements = this.numberOfTMmeasurements + this.numberOfTMmeasurements;
332 this.setMeasurementsTM = true;
333 this.setMeasurements = true;
334 this.setErrorsTM = true;
335 }
336
337 // Enter TM mode data for a range of measurements without weights
338 public void enterTMmodeData(double[]thicknesses, double[] effectiveRIs, double[] modeNumbers){
339 int o = thicknesses.length;
340 int n = effectiveRIs.length;
341 if(n!=o)throw new IllegalArgumentException("number of thicknesses, " + o + ", does not equal the number of effective refractive indices, " + n);
342 int m = modeNumbers.length;
343 if(m!=o)throw new IllegalArgumentException("number of thicknesses, " + o + ", does not equal the number of mode numbers, " + m);
344
345 if(setMeasurementsTM){
346 if(setErrorsTM)throw new IllegalArgumentException("All Entered data must either all have associated errors entered or all have no associated errors entered");
347 int nNew = this.numberOfTMmeasurements + o;
348 double[][] hold = new double[nNew][4];
349 for(int i=0; i<this.numberOfTMmeasurements; i++){
350 for(int j=0; j<4; j++)hold[i][j] = this.measurementsTM[i][j];
351 }
352 for(int i=0; i<o; i++){
353 hold[this.numberOfTMmeasurements + i][0] = thicknesses[i];
354 hold[this.numberOfTMmeasurements + i][1] = effectiveRIs[i];
355 hold[this.numberOfTMmeasurements + i][2] = 1.0D;
356 hold[this.numberOfTMmeasurements + i][3] = modeNumbers[i];
357 }
358 this.measurementsTM = hold;
359 this.numberOfTMmeasurements = nNew;
360 }
361 else{
362 this.numberOfTMmeasurements = o;
363 this.measurementsTM = new double[this.numberOfTMmeasurements][4];
364 for(int i=0; i<this.numberOfTMmeasurements; i++){
365 this.measurementsTM[i][0] = thicknesses[i];
366 this.measurementsTM[i][1] = effectiveRIs[i];
367 this.measurementsTM[i][2] = 1.0D;
368 this.measurementsTM[i][3] = modeNumbers[i];
369 }
370 }
371 this.numberOfMeasurements = this.numberOfTMmeasurements + this.numberOfTMmeasurements;
372 this.setMeasurementsTM = true;
373 this.setMeasurements = true;
374 }
375
376 // Enter TM mode data for a range of measurements with weights
377 public void enterTMmodeData(double[]thicknesses, double[] effectiveRIs, double[] weights, double[] modeNumbers){
378 int o = thicknesses.length;
379 int n = effectiveRIs.length;
380 if(n!=o)throw new IllegalArgumentException("number of thicknesses, " + o + ", does not equal the number of effective refractive indices, " + n);
381 int m = modeNumbers.length;
382 if(m!=o)throw new IllegalArgumentException("number of thicknesses, " + o + ", does not equal the number of mode numbers, " + m);
383
384 if(setMeasurementsTM){
385 if(!setErrorsTM)throw new IllegalArgumentException("All Entered data must either all have associated errors entered or all have no associated errors entered");
386 int nNew = this.numberOfTMmeasurements + o;
387 double[][] hold = new double[nNew][4];
388 for(int i=0; i<this.numberOfTMmeasurements; i++){
389 for(int j=0; j<4; j++)hold[i][j] = this.measurementsTM[i][j];
390 }
391 for(int i=0; i<o; i++){
392 hold[this.numberOfTMmeasurements + i][0] = thicknesses[i];
393 hold[this.numberOfTMmeasurements + i][1] = effectiveRIs[i];
394 hold[this.numberOfTMmeasurements + i][2] = weights[i];
395 hold[this.numberOfTMmeasurements + i][3] = modeNumbers[i];
396 }
397 this.measurementsTM = hold;
398 this.numberOfTMmeasurements = nNew;
399 }
400 else{
401 this.numberOfTMmeasurements = o;
402 this.measurementsTM = new double[this.numberOfTMmeasurements][4];
403 for(int i=0; i<this.numberOfTMmeasurements; i++){
404 this.measurementsTM[i][0] = thicknesses[i];
405 this.measurementsTM[i][1] = effectiveRIs[i];
406 this.measurementsTM[i][2] = weights[i];
407 this.measurementsTM[i][3] = modeNumbers[i];
408 }
409 }
410 this.numberOfMeasurements = this.numberOfTMmeasurements + this.numberOfTMmeasurements;
411 this.setMeasurementsTM = true;
412 this.setMeasurements = true;
413 this.setErrorsTM = true;
414 }
415
416 // Clear entered thickness, effective refractive index and mode number data
417 // so new dat may be entered without it being appended to the existing data
418 public void clearData(){
419 this.numberOfMeasurements = 0;
420 this.setMeasurements = false;
421 this.setWeights = false;
422
423 this.numberOfTEmeasurements = 0;
424 this.setMeasurementsTE = false;
425 this.setErrorsTE = false;
426
427 this.numberOfTMmeasurements = 0;
428 this.setMeasurementsTM = false;
429 this.setErrorsTM = false;
430 }
431
432 // WAVELENGTH
433 // Enter the wavelength (metres)
434 public void setWavelength(double wavelength){
435 this.wavelength = wavelength;
436 this.setWavelength = true;
437 this.ko = 2.0D*Math.PI/this.wavelength;
438 if(!this.setSuperstrate)this.superstrateRefractiveIndex = RefractiveIndex.air(this.wavelength);
439 }
440
441 // SUBSTRATE REFRACTIVE INDEX
442 // Enter the substrate refractive index
443 public void setSubstrateRefractiveIndex(double refIndex){
444 this.substrateRefractiveIndex = refIndex;
445 this.substrateRefractiveIndex2 = refIndex*refIndex;
446 this.setSubstrate= true;
447 }
448
449 // SUPERSTRATE REFRACTIVE INDEX
450 // Enter the superstrate refractive index
451 public void setSuperstrateRefractiveIndex(double refIndex){
452 this.superstrateRefractiveIndex = refIndex;
453 this.superstrateRefractiveIndex2 = refIndex*refIndex;
454 this.setSuperstrate = true;
455 }
456
457 // RETURN SUPERSTRATE REFRACTIVE INDEX
458 // Return superstrate refractive index
459 public double getSuperstrateRefractiveIndex(){
460 if(!this.superCalculationDone && this.setCore)this.calcSuperstrateRefractiveIndex();
461 return this.superstrateRefractiveIndex;
462 }
463
464 // Return standard deviation of the superstrate refractive index
465 public double getStandardDeviationSuperstrateRefractiveIndex(){
466 if(!this.superCalculationDone && this.setCore)this.calcSuperstrateRefractiveIndex();
467 if(this.setCore){
468 if((this.numberOfTMmeasurements+this.numberOfTEmeasurements)==1)System.out.println("Method: getStandardDeviationSuperstrateRefractiveIndex - Only one measurement entered - NO standard deviation returned");
469 }
470 else{
471 System.out.println("Method: getStandardDeviationSuperstrateRefractiveIndex - Superstrate refractive index was entered and NOT calculated - NO standard deviation returned");
472 }
473 return this.sdCoreFilmRefractiveIndex;
474 }
475
476 // CORE FILM REFRACTIVE INDEX
477 // Enter the core film refractive index
478 public void setCoreLayerRefractiveIndex(double refIndex){
479 this.coreFilmRefractiveIndex = refIndex;
480 this.coreFilmRefractiveIndex2 = refIndex*refIndex;
481 this.setCore = true;
482 }
483
484 // RETURN CORE FILM REFRACTIVE INDICES
485 // Return TE mode core film refractive indices
486 public double[] getTEmodeCoreFilmRefractiveIndices(){
487 if(!this.calculationDone)this.calcCoreFilmRefractiveIndices();
488 if(this.numberOfTEmeasurements==0)System.out.println("Method: getTEmodeCoreFilmRefractiveIndices - NO TE mode data entered - NO refractive indices returned");
489 return this.coreFilmTEmodeRefractiveIndices;
490 }
491
492 // Return TM mode core film refractive indices
493 public double[] getTMmodeCoreFilmRefractiveIndices(){
494 if(!this.calculationDone)this.calcCoreFilmRefractiveIndices();
495 if(this.numberOfTMmeasurements==0)System.out.println("Method: getTMmodeCoreFilmRefractiveIndices - NO TM mode data entered - NO refractive indices returned");
496 return this.coreFilmTMmodeRefractiveIndices;
497 }
498
499 // Return TE mode average core film refractive index
500 public double getMeanTEmodeCoreFilmRefractiveIndex(){
501 if(!this.calculationDone)this.calcCoreFilmRefractiveIndices();
502 if(this.numberOfTEmeasurements==0)System.out.println("Method: getMeanTEmodeCoreFilmRefractiveIndices - NO TE mode data entered - NO refractive index returned");
503 return this.meanTEmodeCoreFilmRefractiveIndex;
504 }
505
506 // Return TM mode average core film refractive index
507 public double getMeanTMmodeCoreFilmRefractiveIndex(){
508 if(!this.calculationDone)this.calcCoreFilmRefractiveIndices();
509 if(this.numberOfTMmeasurements==0)System.out.println("Method: getMeanTMmodeCoreFilmRefractiveIndices - NO TM mode data entered - NO refractive index returned");
510 return this.meanTMmodeCoreFilmRefractiveIndex;
511 }
512
513 // Return overall average core film refractive index
514 public double getMeanCoreFilmRefractiveIndex(){
515 if(!this.calculationDone)this.calcCoreFilmRefractiveIndices();
516 return this.meanCoreFilmRefractiveIndex;
517 }
518
519 // Return core film refractive index
520 public double getCoreFilmRefractiveIndex(){
521 if(!this.calculationDone && !this.setCore)this.calcCoreFilmRefractiveIndices();
522 return this.coreFilmRefractiveIndex;
523 }
524
525 // Return standard deviation of the core film TE mode refractive index
526 public double getStandardDeviationTEmodeCoreFilmRefractiveIndex(){
527 if(!this.calculationDone)this.calcCoreFilmRefractiveIndices();
528 if(this.numberOfTEmeasurements==0)System.out.println("Method: getStandardDeviationTEmodeCoreFilmRefractiveIndex - NO TE mode data entered - NO standard deviation returned");
529 if(this.numberOfTEmeasurements==1)System.out.println("Method: getStandardDeviationTEmodeCoreFilmRefractiveIndex - Only one measurement entered - NO standard deviation returned");
530 return this.sdTEmodeCoreFilmRefractiveIndex;
531 }
532
533 // Return standard deviation of the core film TM mode refractive index
534 public double getStandardDeviationTMmodeCoreFilmRefractiveIndex(){
535 if(!this.calculationDone)this.calcCoreFilmRefractiveIndices();
536 if(this.numberOfTMmeasurements==0)System.out.println("Method: getStandardDeviationTMmodeCoreFilmRefractiveIndex - NO TM mode data entered - NO standard deviation returned");
537 if(this.numberOfTMmeasurements==1)System.out.println("Method: getStandardDeviationTMmodeCoreFilmRefractiveIndex - Only one measurement entered - NO standard deviation returned");
538 return this.sdTMmodeCoreFilmRefractiveIndex;
539 }
540
541 // Return standard deviation of the overall core film refractive index
542 public double getStandardDeviationCoreFilmRefractiveIndex(){
543 if(!this.calculationDone)this.calcCoreFilmRefractiveIndices();
544 if((this.numberOfTMmeasurements+this.numberOfTEmeasurements)==1)System.out.println("Method: getStandardDeviationCoreFilmRefractiveIndex - Only one measurement entered - NO standard deviation returned");
545 return this.sdCoreFilmRefractiveIndex;
546 }
547
548 // EFFECTIVE REFRACTIVE INDICES
549 // Return experimental TE mode effective refractive indices
550 public double[][] getTEmodeExperimentalEffectiveRefractiveIndices(){
551 double[][] returnedArray = null;
552 if(this.numberOfTEmeasurements==0){
553 System.out.println("Method: getTEmodeExperimentalEffectiveRefractiveIndices - NO TE mode data entered - NO effective refractive indices returned");
554 }
555 else{
556 returnedArray = new double[2][this.numberOfTEmeasurements];
557 returnedArray[0] = this.thicknessesUsedTE;
558 for(int i=0; i<this.numberOfTEmeasurements; i++){
559 returnedArray[1][i] = this.measurementsTE[i][1];
560 }
561 }
562 return returnedArray;
563 }
564
565 // Return errors in the experimental TE mode effective refractive indices
566 public double[][] getTEmodeEffectiveRefractiveIndicesErrors(){
567 double[][] returnedArray = null;
568 if(this.numberOfTEmeasurements==0){
569 System.out.println("Method: getTEmodeExperimentalEffectiveRefractiveIndices - NO TE mode data entered - NO errors returned");
570 }
571 else{
572 if(!this.setErrorsTE){
573 System.out.println("Method: getTEmodeExperimentalEffectiveRefractiveIndices - NO TE mode errors entered - NO errors returned");
574 }
575 else{
576 returnedArray = new double[2][this.numberOfTEmeasurements];
577 returnedArray[0] = this.thicknessesUsedTE;
578 for(int i=0; i<this.numberOfTEmeasurements; i++){
579 returnedArray[1][i] = this.measurementsTE[i][2];
580 }
581 }
582 }
583 return returnedArray;
584 }
585
586 // Return experimental TM mode effective refractive indices
587 public double[][] getTMmodeExperimentalEffectiveRefractiveIndices(){
588 double[][] returnedArray = null;
589 if(this.numberOfTMmeasurements==0){
590 System.out.println("Method: getTMmodeExperimentalEffectiveRefractiveIndices - NO TM mode data entered - NO effective refractive indices returned");
591 }
592 else{
593 returnedArray = new double[2][this.numberOfTMmeasurements];
594 returnedArray[0] = this.thicknessesUsedTM;
595 for(int i=0; i<this.numberOfTMmeasurements; i++){
596 returnedArray[1][i] = this.measurementsTM[i][1];
597 }
598 }
599 return returnedArray;
600 }
601
602 // Return errors in the experimental TM mode effective refractive indices
603 public double[][] getTMmodeEffectiveRefractiveIndicesErrors(){
604 double[][] returnedArray = null;
605 if(this.numberOfTMmeasurements==0){
606 System.out.println("Method: getTMmodeExperimentalEffectiveRefractiveIndices - NO TM mode data entered - NO errors returned");
607 }
608 else{
609 if(!this.setErrorsTM){
610 System.out.println("Method: getTMmodeExperimentalEffectiveRefractiveIndices - NO TM mode errors entered - NO errors returned");
611 }
612 else{
613 returnedArray = new double[2][this.numberOfTMmeasurements];
614 returnedArray[0] = this.thicknessesUsedTM;
615 for(int i=0; i<this.numberOfTMmeasurements; i++){
616 returnedArray[1][i] = this.measurementsTM[i][2];
617 }
618 }
619 }
620 return returnedArray;
621 }
622
623 // Return calculated TE mode effective refractive indices for the calculated mean core refractive index
624 public double[][] getTEmodeCalculatedEffectiveRefractiveIndices(){
625 if(!this.calculationDone)this.calcCoreFilmRefractiveIndices();
626 if(this.numberOfTEmeasurements==0)System.out.println("Method: getStandardDeviationTEmodeCoreFilmRefractiveIndices - NO TE mode data entered - NO effective refractive indices returned");
627 double[][] returnedArray = new double[2][this.numberOfTEmeasurements];
628
629 // Create instance of the class holding the TE mode effective refractive index function
630 FunctTEplot func = new FunctTEplot();
631
632 // Set function parameters
633 func.substrateRefractiveIndex2 = this.substrateRefractiveIndex2;
634 func.superstrateRefractiveIndex2 = this.superstrateRefractiveIndex2;
635 func.coreFilmRefractiveIndex2 = this.coreFilmRefractiveIndex2;
636 func.prismRefractiveIndex2 = this.prismRefractiveIndex2;
637 func.prismToWaveguideGap = this.prismToWaveguideGap;
638 func.setPrismToWaveguideGap = this.setPrismToWaveguideGap;
639 func.ko = this.ko;
640
641 this.lowerBound = Math.max(this.substrateRefractiveIndex, this.superstrateRefractiveIndex);
642 this.upperBound = Math.min(this.coreFilmRefractiveIndex, this.prismRefractiveIndex);
643
644 for(int i=0; i<this.numberOfTEmeasurements; i++){
645
646 // set further function parameter
647 func.thickness = this.measurementsTE[i][0];
648 func.modeNumber = this.measurementsTE[i][3];
649
650 // call root searching method, bisection
651 RealRoot rr = new RealRoot();
652 rr.noBoundsExtensions();
653 rr.setTolerance(this.tolerance);
654 this.calcEffectRefrIndicesTE[i] = rr.bisect(func, this.lowerBound, this.upperBound);
655 }
656 returnedArray[0] = this.thicknessesUsedTE;
657 returnedArray[1] = this.calcEffectRefrIndicesTE;
658
659 return returnedArray;
660 }
661
662 // Return calculated TM mode effective refractive indices for the calculated mean core refractive index
663 public double[][] getTMmodeCalculatedEffectiveRefractiveIndices(){
664 if(!this.calculationDone)this.calcCoreFilmRefractiveIndices();
665 if(this.numberOfTMmeasurements==0)System.out.println("Method: getStandardDeviationTMmodeCoreFilmRefractiveIndices - NO TM mode data entered - NO effective refractive indices returned");
666 double[][] returnedArray = new double[2][this.numberOfTMmeasurements];
667
668 // Create instance of the class holding the TM mode effective refractive index function
669 FunctTMplot func = new FunctTMplot();
670
671 // Set function parameters
672 func.substrateRefractiveIndex2 = this.substrateRefractiveIndex2;
673 func.superstrateRefractiveIndex2 = this.superstrateRefractiveIndex2;
674 func.coreFilmRefractiveIndex2 = this.coreFilmRefractiveIndex2;
675 func.prismRefractiveIndex2 = this.prismRefractiveIndex2;
676 func.prismToWaveguideGap = this.prismToWaveguideGap;
677 func.setPrismToWaveguideGap = this.setPrismToWaveguideGap;
678 func.ko = this.ko;
679
680 this.lowerBound = Math.max(this.substrateRefractiveIndex, this.superstrateRefractiveIndex);
681 this.upperBound = Math.min(this.coreFilmRefractiveIndex, this.prismRefractiveIndex);
682
683 for(int i=0; i<this.numberOfTMmeasurements; i++){
684
685 // set further function parameter
686 func.thickness = this.measurementsTM[i][0];
687 func.modeNumber = this.measurementsTM[i][3];
688
689 // call root searching method, bisection
690 RealRoot rr = new RealRoot();
691 rr.noBoundsExtensions();
692 rr.setTolerance(this.tolerance);
693 this.calcEffectRefrIndicesTM[i] = rr.bisect(func, this.lowerBound, this.upperBound);
694 }
695 returnedArray[0] = this.thicknessesUsedTM;
696 returnedArray[1] = this.calcEffectRefrIndicesTM;
697
698 return returnedArray;
699 }
700
701 // CALCULATION OF THE GUIDING CORE FILM REFRACTIVE INDEX/INDICES
702 public void calcCoreFilmRefractiveIndices(){
703 if(!this.setMeasurements)throw new IllegalArgumentException("Either no thickness, angle/effective refractive index, mode number data has been entered or a key subclass variable, e.g. coupling prism corner angle has not been entered");
704 if(!this.setWavelength)throw new IllegalArgumentException("No wavelength has been entered");
705 if(!this.setSubstrate)throw new IllegalArgumentException("No substrate refractive index has been entered");
706
707 // Set the bounds and eliminate points where effective ref. index < substrate or superstrate ref. index
708 this.lowerBound = Math.max(this.substrateRefractiveIndex, this.superstrateRefractiveIndex);
709 this.upperBound = 0.0D;
710
711 if(this.numberOfTEmeasurements>0)this.eliminatedTE = new boolean[this.numberOfTEmeasurements];
712 int elimNumberTE = 0;
713 for(int i=0; i<this.numberOfTEmeasurements; i++){
714 this.eliminatedTE[i] = false;
715 if(this.measurementsTE[i][1]<this.lowerBound){
716 System.out.println("TE mode measurement point, " + i + ", eliminated as the effective refractive index, " + this.measurementsTE[i][1] + ", lies below the physical limit, " + this.lowerBound);
717 this.eliminatedTE[i] = true;
718 elimNumberTE++;
719 }
720 else{
721 if(this.upperBound<this.measurementsTE[i][1])this.upperBound = this.measurementsTE[i][1];
722 }
723 }
724 if(elimNumberTE>0){
725 int newNumber = this.numberOfTEmeasurements - elimNumberTE;
726 if(newNumber==0){
727 this.numberOfTEmeasurements = 0;
728 }
729 else{
730 double[][] temp = new double[newNumber][3];
731 int nIndex = 0;
732 for(int i=0; i<this.numberOfTEmeasurements; i++){
733 if(!this.eliminatedTE[i]){
734 temp[nIndex][0] = this.measurementsTE[i][0];
735 temp[nIndex][1] = this.measurementsTE[i][1];
736 temp[nIndex][2] = this.measurementsTE[i][2];
737 temp[nIndex][3] = this.measurementsTE[i][3];
738 nIndex++;
739 }
740 }
741 this.measurementsTE = temp;
742 this.numberOfTEmeasurements = newNumber;
743 this.numberOfMeasurements = this.numberOfTEmeasurements + this.numberOfTMmeasurements;
744 }
745 }
746 this.thicknessesUsedTE = new double[this.numberOfTEmeasurements];
747 this.calcEffectRefrIndicesTE = new double[this.numberOfTEmeasurements];
748 for(int i=0; i<this.numberOfTEmeasurements; i++)this.thicknessesUsedTE[i] = this.measurementsTE[i][0];
749 this.maximumTEmodeEffectiveRefractiveIndex = this.upperBound;
750
751 this.upperBound = 0.0D;
752 if(this.numberOfTMmeasurements>0)this.eliminatedTM = new boolean[this.numberOfTMmeasurements];
753 int elimNumberTM = 0;
754 for(int i=0; i<this.numberOfTMmeasurements; i++){
755 this.eliminatedTM[i] = false;
756 if(this.measurementsTM[i][1]<this.lowerBound){
757 System.out.println("TM mode measurement point, " + i + ", eliminated as the effective refractive index, " + this.measurementsTM[i][1] + ", lies below the physical limit, " + this.lowerBound);
758 this.eliminatedTM[i] = true;
759 elimNumberTM++;
760 }
761 else{
762 if(this.upperBound<this.measurementsTM[i][1])this.upperBound = this.measurementsTM[i][1];
763 }
764 }
765 if(elimNumberTM>0){
766 int newNumber = this.numberOfTMmeasurements - elimNumberTM;
767 if(newNumber==0){
768 this.numberOfTMmeasurements = 0;
769 }
770 else{
771 double[][] temp = new double[newNumber][3];
772 int nIndex = 0;
773 for(int i=0; i<this.numberOfTMmeasurements; i++){
774 if(!this.eliminatedTM[i]){
775 temp[nIndex][0] = this.measurementsTM[i][0];
776 temp[nIndex][1] = this.measurementsTM[i][1];
777 temp[nIndex][2] = this.measurementsTM[i][2];
778 temp[nIndex][3] = this.measurementsTM[i][3];
779 nIndex++;
780 }
781 }
782 this.measurementsTM = temp;
783 this.numberOfTMmeasurements = newNumber;
784 this.numberOfMeasurements = this.numberOfTEmeasurements + this.numberOfTMmeasurements;
785 }
786 }
787 this.thicknessesUsedTM = new double[this.numberOfTMmeasurements];
788 this.calcEffectRefrIndicesTM = new double[this.numberOfTMmeasurements];
789 for(int i=0; i<this.numberOfTMmeasurements; i++)this.thicknessesUsedTM[i] = this.measurementsTM[i][0];
790 this.maximumTMmodeEffectiveRefractiveIndex = this.upperBound;
791
792 if(this.numberOfMeasurements==0)throw new IllegalArgumentException("All data points rejected as lying outside the physically meaningful bounds");
793
794 if(this.fixedPrismToWaveguideGap){
795 this.calcCoreFilmRefractiveIndicesFixedGap();
796 }
797 else{
798 this.calcCoreFilmRefractiveIndicesEstimatedGap();
799 }
800 }
801
802 // Calculates core refractive index and the prism to waveguide gap
803 public void calcCoreFilmRefractiveIndicesEstimatedGap(){
804
805 // ArrayList to store sum of squares on each gap distance decrement
806 ArrayList<Double> arrayl = new ArrayList<Double>();
807
808 // initial gap distance
809 this.prismToWaveguideGap = 1.e1;
810
811 // set calculation to fixed gap for each gap decrement calculation
812 this.fixedPrismToWaveguideGap = true;
813
814 // arrays to store experimental and, at each gap decrement, the calculated effective refractive indices
815 double[] effectExpl = new double[this.numberOfMeasurements];
816 double[] effectCalc = new double[this.numberOfMeasurements];
817
818 // Collect experimental effective refractive indices
819 for(int i=0; i<this.numberOfTEmeasurements; i++)effectExpl[i] = this.measurementsTE[i][1];
820 for(int i=0; i<this.numberOfTMmeasurements; i++)effectExpl[i + this.numberOfTEmeasurements] = this.measurementsTM[i][1];
821
822 // Sum of squares of experimental - calculated effective refractive indices at each gap decrement
823 double sumOfSquares = 0.0D;
824
825 // Sum of squares at preceding gap decrement
826 double sumOfSquaresLast = Double.POSITIVE_INFINITY;
827
828 // Number of decrements
829 int numberOfDecrements = 0;
830
831 // Decrementing loop in which sum of squares calculted
832 boolean test = true;
833 while(test){
834
835 // Set flags to allow new calculation of core refractive index
836 this.setCore = false;
837 this.calculationDone = false;
838 this.fixedPrismToWaveguideGap = true;
839 this.setPrismToWaveguideGap=true;
840
841 // Get mean core refractive index at current gap value
842 double coreRI = this.getMeanCoreFilmRefractiveIndex();
843
844 // Check whether physically meaningful root found
845 if(coreRI!=coreRI){
846 System.out.println("NaN");
847 test = false;
848 }
849 else{
850 // Calculate sum of squares
851 double[][] effectTECalc = this.getTEmodeCalculatedEffectiveRefractiveIndices();
852 for(int i=0; i<this.numberOfTEmeasurements; i++)effectCalc[i] = effectTECalc[1][i];
853 double[][] effectTMCalc = this.getTMmodeCalculatedEffectiveRefractiveIndices();
854 for(int i=0; i<this.numberOfTMmeasurements; i++)effectCalc[i + this.numberOfTEmeasurements] = effectTMCalc[1][i];
855 sumOfSquares = 0.0D;
856 for(int i=0; i<this.numberOfMeasurements; i++)sumOfSquares += Fmath.square(effectExpl[i] - effectCalc[i]);
857
858 // store values
859 System.out.println(this.prismToWaveguideGap + " " + coreRI + " " + sumOfSquares);
860 arrayl.add(new Double(coreRI));
861 arrayl.add(new Double(sumOfSquares));
862 numberOfDecrements++;
863
864 // Decrement gap distance and check for termination gap distance
865 this.prismToWaveguideGap /= 2.0;
866 if(this.prismToWaveguideGap<1.0e-10)test = false;
867 }
868 }
869 }
870
871
872 // Calculates core refractive index for either fixed prism to waveguide gap or on ignoring prism perturbation
873 public void calcCoreFilmRefractiveIndicesFixedGap(){
874 // call the root search methods to obtain the core refractive index/indices
875 if(this.numberOfTEmeasurements>0)this.calcTEmodeCoreFilmRefractiveIndices();
876 if(this.numberOfTMmeasurements>0)this.calcTMmodeCoreFilmRefractiveIndices();
877
878 // Calculate the overall mean and standard deviation of the core refractive indices
879 if(this.numberOfTEmeasurements>0 && this.numberOfTMmeasurements==0){
880 this.meanCoreFilmRefractiveIndex = this.meanTEmodeCoreFilmRefractiveIndex;
881 this.coreFilmRefractiveIndex = this.meanCoreFilmRefractiveIndex;
882 this.sdCoreFilmRefractiveIndex = this.sdTEmodeCoreFilmRefractiveIndex;
883 }
884 else{
885 if(this.numberOfTMmeasurements>0 && this.numberOfTEmeasurements==0){
886 this.meanCoreFilmRefractiveIndex = this.meanTMmodeCoreFilmRefractiveIndex;
887 this.coreFilmRefractiveIndex = this.meanCoreFilmRefractiveIndex;
888 this.sdCoreFilmRefractiveIndex = this.sdTMmodeCoreFilmRefractiveIndex;
889 }
890 else{
891 double[] values = new double[this.numberOfMeasurements];
892 double[] weights = new double[this.numberOfMeasurements];
893 for(int i=0; i<this.numberOfTEmeasurements; i++){
894 values[i] = this.coreFilmTEmodeRefractiveIndices[i];
895 weights[i] = this.measurementsTE[i][2];
896 }
897 for(int i=0; i<this.numberOfTMmeasurements; i++){
898 values[i+this.numberOfTEmeasurements] = this.coreFilmTMmodeRefractiveIndices[i];
899 weights[i+this.numberOfTEmeasurements] = this.measurementsTM[i][2];
900 }
901 this.meanCoreFilmRefractiveIndex = Stat.mean(values, weights);
902 this.sdCoreFilmRefractiveIndex = Stat.standardDeviation(values, weights);
903 this.coreFilmRefractiveIndex = this.meanCoreFilmRefractiveIndex;
904 }
905 }
906
907 this.meanCoreFilmRefractiveIndex2 = this.meanCoreFilmRefractiveIndex*this.meanCoreFilmRefractiveIndex;
908 this.coreFilmRefractiveIndex2 = this.meanCoreFilmRefractiveIndex2;
909 this.maximumEffectiveRefractiveIndex = Math.max(this.maximumTEmodeEffectiveRefractiveIndex, this.maximumTMmodeEffectiveRefractiveIndex);
910 this.setCore = true;
911 this.calculationDone = true;
912 }
913
914 // Calculate TE mode refractive indices
915 public void calcTEmodeCoreFilmRefractiveIndices(){
916
917 this.coreFilmTEmodeRefractiveIndices = new double[this.numberOfTEmeasurements];
918
919 // Create instance of the class holding the TE mode core film refractive indexfunction
920 FunctTE func = new FunctTE();
921
922 // Set function parameters
923 func.substrateRefractiveIndex2 = this.substrateRefractiveIndex2;
924 func.superstrateRefractiveIndex2 = this.superstrateRefractiveIndex2;
925 func.prismRefractiveIndex2 = this.prismRefractiveIndex2;
926 func.prismToWaveguideGap = this.prismToWaveguideGap;
927 func.setPrismToWaveguideGap = this.setPrismToWaveguideGap;
928 func.ko = this.ko;
929
930 double[] weights = new double[this.numberOfTEmeasurements];
931 this.lowerBound = this.maximumTEmodeEffectiveRefractiveIndex;
932 this.upperBound = 2.0D*this.lowerBound;
933 for(int i=0; i<this.numberOfTEmeasurements; i++){
934 weights[i] = this.measurementsTE[i][2];
935
936 // set further function parameters
937 func.thickness = this.measurementsTE[i][0];
938 func.effectiveRefractiveIndex2 = this.measurementsTE[i][1]*this.measurementsTE[i][1];
939 func.modeNumber = this.measurementsTE[i][3];
940
941 // call root searching method, bisection, to obtain core refractive index
942 RealRoot rr = new RealRoot();
943 rr.noLowerBoundExtension();
944 rr.setTolerance(this.tolerance);
945 this.coreFilmTEmodeRefractiveIndices[i] = rr.bisect(func, this.lowerBound, this.upperBound);
946 }
947
948 // Calculate mean and sd
949 if(this.numberOfTEmeasurements>1){
950 this.meanTEmodeCoreFilmRefractiveIndex = Stat.mean(this.coreFilmTEmodeRefractiveIndices, weights);
951 this.sdTEmodeCoreFilmRefractiveIndex = Stat.standardDeviation(this.coreFilmTEmodeRefractiveIndices, weights);
952 }
953 else{
954 this.meanTEmodeCoreFilmRefractiveIndex = this.coreFilmTEmodeRefractiveIndices[0];
955 }
956 }
957
958 // Calculate TM mode refractive indices
959 public void calcTMmodeCoreFilmRefractiveIndices(){
960
961 this.coreFilmTMmodeRefractiveIndices = new double[this.numberOfTMmeasurements];
962
963 // Create instance of the class holding the TE mode core film refractive index function
964 FunctTM func = new FunctTM();
965
966 // Set function parameters
967 func.substrateRefractiveIndex2 = this.substrateRefractiveIndex2;
968 func.superstrateRefractiveIndex2 = this.superstrateRefractiveIndex2;
969 func.prismRefractiveIndex2 = this.prismRefractiveIndex2;
970 func.prismToWaveguideGap = this.prismToWaveguideGap;
971 func.setPrismToWaveguideGap = this.setPrismToWaveguideGap;
972 func.ko = this.ko;
973
974 double[] weights = new double[this.numberOfTMmeasurements];
975 this.lowerBound = this.maximumTMmodeEffectiveRefractiveIndex;
976 this.upperBound = 2.0D*this.lowerBound;
977 for(int i=0; i<this.numberOfTMmeasurements; i++){
978 weights[i] = this.measurementsTM[i][2];
979
980 // set further function parameters
981 func.thickness = this.measurementsTM[i][0];
982 func.effectiveRefractiveIndex2 = this.measurementsTM[i][1]*this.measurementsTM[i][1];
983 func.modeNumber = this.measurementsTM[i][3];
984
985 // call root searching method, bisection, to obtain core refractive index
986 RealRoot rr = new RealRoot();
987 rr.noLowerBoundExtension();
988 rr.setTolerance(this.tolerance);
989 this.coreFilmTMmodeRefractiveIndices[i] = rr.bisect(func, this.lowerBound, this.upperBound);
990 }
991
992 // Calculate mean and sd
993 if(this.numberOfTMmeasurements>1){
994 this.meanTMmodeCoreFilmRefractiveIndex = Stat.mean(this.coreFilmTMmodeRefractiveIndices, weights);
995 this.sdTMmodeCoreFilmRefractiveIndex = Stat.standardDeviation(this.coreFilmTMmodeRefractiveIndices, weights);
996 }
997 else{
998 this.meanTMmodeCoreFilmRefractiveIndex = this.coreFilmTMmodeRefractiveIndices[0];
999 }
1000 }
1001
1002 // Calculate a TE mode dispersion curve
1003 public double[][] dispersionCurveTE(double lowThickness, double highThickness, int numberOfPoints, double modeNumber){
1004 if(!this.setWavelength)throw new IllegalArgumentException("No wavelength has been entered");
1005 if(!this.setSubstrate)throw new IllegalArgumentException("No substrate refractive index has been entered");
1006 if(!this.setCore)throw new IllegalArgumentException("No core film refractive index has been calculated or entered");
1007
1008 // Create arrays
1009 double[] thickness = new double[numberOfPoints];
1010 double[] effective = new double[numberOfPoints];
1011 double[][] returnedArray = new double[2][numberOfPoints];
1012 double incr = (Fmath.log10(highThickness) - Fmath.log10(lowThickness))/(numberOfPoints - 1);
1013 thickness[0] = Fmath.log10(lowThickness);
1014 thickness[numberOfPoints-1] = Fmath.log10(highThickness);
1015 for(int i=1; i<numberOfPoints-1; i++)thickness[i] = thickness[i-1] + incr;
1016 returnedArray[0] = thickness;
1017
1018 // Create instance of the class holding the TE mode effective refractive index function
1019 FunctTEplot func = new FunctTEplot();
1020
1021 // Set function parameters
1022 func.substrateRefractiveIndex2 = this.substrateRefractiveIndex2;
1023 func.superstrateRefractiveIndex2 = this.superstrateRefractiveIndex2;
1024 func.coreFilmRefractiveIndex2 = this.coreFilmRefractiveIndex2;
1025 func.prismRefractiveIndex2 = this.prismRefractiveIndex2;
1026 func.prismToWaveguideGap = this.prismToWaveguideGap;
1027 func.setPrismToWaveguideGap = this.setPrismToWaveguideGap;
1028 func.ko = this.ko;
1029 func.modeNumber = modeNumber;
1030
1031 this.lowerBound = Math.max(this.substrateRefractiveIndex, this.superstrateRefractiveIndex);
1032 this.upperBound = Math.min(this.coreFilmRefractiveIndex, this.prismRefractiveIndex);
1033
1034 for(int i=0; i<numberOfPoints; i++){
1035 // set further function parameter
1036 func.thickness = Math.pow(10.0D, thickness[i]);
1037
1038 // call root searching method, bisection
1039 RealRoot rr = new RealRoot();
1040 rr.noBoundsExtensions();
1041 rr.setTolerance(this.tolerance);
1042 effective[i] = rr.bisect(func, this.lowerBound, this.upperBound);
1043 }
1044 returnedArray[1] = effective;
1045 return returnedArray;
1046 }
1047
1048 // Calculate a TM mode dispersion curve
1049 public double[][] dispersionCurveTM(double lowThickness, double highThickness, int numberOfPoints, double modeNumber){
1050 if(!this.setWavelength)throw new IllegalArgumentException("No wavelength has been entered");
1051 if(!this.setSubstrate)throw new IllegalArgumentException("No substrate refractive index has been entered");
1052 if(!this.setCore)throw new IllegalArgumentException("No core film refractive index has been calculated or entered");
1053
1054 // Create arrays
1055 double[] thickness = new double[numberOfPoints];
1056 double[] effective = new double[numberOfPoints];
1057 double[][] returnedArray = new double[2][numberOfPoints];
1058 double incr = (Fmath.log10(highThickness) - Fmath.log10(lowThickness))/(numberOfPoints - 1);
1059 thickness[0] = Fmath.log10(lowThickness);
1060 thickness[numberOfPoints-1] = Fmath.log10(highThickness);
1061 for(int i=1; i<numberOfPoints-1; i++)thickness[i] = thickness[i-1] + incr;
1062 returnedArray[0] = thickness;
1063
1064 // Create instance of the class holding the TM mode effective refractive index function
1065 FunctTMplot func = new FunctTMplot();
1066
1067 // Set function parameters
1068 func.substrateRefractiveIndex2 = this.substrateRefractiveIndex2;
1069 func.superstrateRefractiveIndex2 = this.superstrateRefractiveIndex2;
1070 func.coreFilmRefractiveIndex2 = this.coreFilmRefractiveIndex2;
1071 func.prismRefractiveIndex2 = this.prismRefractiveIndex2;
1072 func.prismToWaveguideGap = this.prismToWaveguideGap;
1073 func.setPrismToWaveguideGap = this.setPrismToWaveguideGap;
1074 func.ko = this.ko;
1075 func.modeNumber = modeNumber;
1076
1077 this.lowerBound = Math.max(this.substrateRefractiveIndex, this.superstrateRefractiveIndex);
1078 this.upperBound = Math.min(this.coreFilmRefractiveIndex, this.prismRefractiveIndex);
1079 for(int i=0; i<numberOfPoints; i++){
1080 // set further function parameter
1081 func.thickness = Math.pow(10.0D, thickness[i]);
1082
1083 // call root searching method, bisection
1084 RealRoot rr = new RealRoot();
1085 rr.noBoundsExtensions();
1086 rr.setTolerance(this.tolerance);
1087 effective[i] = rr.bisect(func, this.lowerBound, this.upperBound);
1088 }
1089 returnedArray[1] = effective;
1090 return returnedArray;
1091 }
1092
1093 // Calculate and plot a TE dispersion curve
1094 // Graph title not provided
1095 public double[][] plotDispersionCurveTE(double lowThickness, double highThickness, int numberOfPoints, double modeNumber){
1096 String legend1 = " ";
1097 return this.plotDispersionCurveTE(lowThickness, highThickness, numberOfPoints, modeNumber, legend1);
1098 }
1099
1100 // Calculate and plot a TE dispersion curve
1101 // Graph title provided
1102 public double[][] plotDispersionCurveTE(double lowThickness, double highThickness, int numberOfPoints, double modeNumber, String legend1){
1103
1104 //Calculate curve
1105 double[][] curve = dispersionCurveTE(lowThickness, highThickness, numberOfPoints, modeNumber);
1106
1107 // Create instance of PlotGraph
1108 PlotGraph pg1 = new PlotGraph(curve);
1109 int lineOption = 3;
1110 if(numberOfPoints<100)lineOption = 1;
1111 pg1.setLine(lineOption);
1112 pg1.setPoint(0);
1113 String legend0 = "Dispersion curve: TE mode - mode number " + (int)modeNumber;
1114 pg1.setGraphTitle(legend0);
1115 pg1.setGraphTitle2(legend1);
1116 pg1.setXaxisLegend("Log10( Core Film Thickness / metres )");
1117 pg1.setYaxisLegend("Effective Refractive Index (kz/ko)");
1118
1119 // Plot graph
1120 pg1.plot();
1121
1122 // Return calculated curve values
1123 return curve;
1124 }
1125
1126 // Calculate and plot a TM dispersion curve
1127 // Graph title not provided
1128 public double[][] plotDispersionCurveTM(double lowThickness, double highThickness, int numberOfPoints, double modeNumber){
1129 String legend1 = " ";
1130 return this.plotDispersionCurveTM(lowThickness, highThickness, numberOfPoints, modeNumber, legend1);
1131 }
1132
1133 // Calculate and plot a TM dispersion curve
1134 // Graph title provided
1135 public double[][] plotDispersionCurveTM(double lowThickness, double highThickness, int numberOfPoints, double modeNumber, String legend1){
1136
1137 //Calculate curve
1138 double[][] curve = dispersionCurveTM(lowThickness, highThickness, numberOfPoints, modeNumber);
1139
1140 // Create instance of PlotGraph
1141 PlotGraph pg2 = new PlotGraph(curve);
1142 int lineOption = 3;
1143 if(numberOfPoints<100)lineOption = 1;
1144 pg2.setLine(lineOption);
1145 pg2.setPoint(0);
1146 String legend0 = "Dispersion curve: TM mode - mode number " + (int)modeNumber;
1147 pg2.setGraphTitle(legend0);
1148 pg2.setGraphTitle2(legend1);
1149 pg2.setXaxisLegend("Log10( Core Film Thickness / metres )");
1150 pg2.setYaxisLegend("Effective Refractive Index (kz/ko)");
1151
1152 // Plot graph
1153 pg2.plot();
1154
1155 // Return calculated curve values
1156 return curve;
1157 }
1158
1159 // PLOT FITTED DISPERSION CURVE
1160 // Graph title not provided
1161 public void plotFittedDispersionCurves(){
1162 String legend = "PlanarWaveguide.plotDispersion - Dispersion Plot";
1163 this.plotFittedDispersionCurve(legend);
1164 }
1165
1166 // Graph title provided
1167 public void plotFittedDispersionCurve(String legend){
1168
1169 if(!this.calculationDone)this.calcCoreFilmRefractiveIndices();
1170
1171 // separate TE mode orders
1172 ArrayList<Object> arraylTE = null;
1173 int pOrderNumberTE = 0;
1174 int pOrdersCheckedTE = 0;
1175 int maximumNumberOfPoints = 0;
1176 if(this.numberOfTEmeasurements>0){
1177 arraylTE = new ArrayList<Object>();
1178 boolean testModes = true;
1179 int pOrder = 0;
1180 int numberTestedPositive = 0;
1181 while(testModes){
1182 int pNumber = 0;
1183 for(int i=0; i<this.numberOfTEmeasurements; i++){
1184 if(this.measurementsTE[i][3]==pOrder){
1185 pNumber++;
1186 numberTestedPositive++;
1187 arraylTE.add(new Double(this.measurementsTE[i][0]));
1188 arraylTE.add(new Double(this.measurementsTE[i][1]));
1189 }
1190 }
1191 arraylTE.add(2*pOrder, new Integer(pOrder));
1192 arraylTE.add(2*pOrder+1, new Integer(pNumber));
1193 if(pNumber>0)pOrderNumberTE++;
1194 if(pNumber>maximumNumberOfPoints)maximumNumberOfPoints = pNumber;
1195 if(numberTestedPositive==this.numberOfTEmeasurements){
1196 testModes=false;
1197 }
1198 else{
1199 pOrder++;
1200 }
1201 }
1202 pOrdersCheckedTE = pOrder;
1203 }
1204 int numberOfCurves = pOrderNumberTE;
1205
1206 // separate TM mode orders
1207 ArrayList<Object> arraylTM = null;
1208 int pOrderNumberTM = 0;
1209 int pOrdersCheckedTM = 0;
1210 if(this.numberOfTMmeasurements>0){
1211 arraylTM = new ArrayList<Object>();
1212 boolean testModes = true;
1213 int pOrder = 0;
1214 int numberTestedPositive = 0;
1215 while(testModes){
1216 int pNumber = 0;
1217 for(int i=0; i<this.numberOfTMmeasurements; i++){
1218 if(this.measurementsTM[i][3]==pOrder){
1219 pNumber++;
1220 numberTestedPositive++;
1221 arraylTM.add(new Double(this.measurementsTM[i][0]));
1222 arraylTM.add(new Double(this.measurementsTM[i][1]));
1223 }
1224 }
1225 arraylTM.add(2*pOrder, new Integer(pOrder));
1226 arraylTM.add(2*pOrder+1, new Integer(pNumber));
1227 if(pNumber>0)pOrderNumberTM++;
1228 if(pNumber>maximumNumberOfPoints)maximumNumberOfPoints = pNumber;
1229 if(numberTestedPositive==this.numberOfTMmeasurements){
1230 testModes=false;
1231 }
1232 else{
1233 pOrder++;
1234 }
1235 }
1236 pOrdersCheckedTM = pOrder;
1237 }
1238 numberOfCurves += pOrderNumberTM;
1239 numberOfCurves *= 2;
1240 if(maximumNumberOfPoints<200)maximumNumberOfPoints = 200;
1241
1242
1243 // Set up plotting data arrays
1244 double[][] plotData = PlotGraph.data(numberOfCurves, maximumNumberOfPoints);
1245 double[] modeNumber = new double[numberOfCurves];
1246 String[] modeType = new String[numberOfCurves];
1247
1248 int atCurveNumber = 0;
1249 int plotNumber = 0;
1250 // TE mode curves
1251 int arraylIndex = 2*(pOrdersCheckedTE+1);
1252 int arraylHeaderIndex = 1;
1253 double tempD = 0.0D;
1254 int tempI = 0;
1255
1256 if(this.numberOfTEmeasurements>0){
1257 int testVec = 0;
1258 int arraylSize = arraylTE.size();
1259 while(testVec<arraylSize){
1260 // Check mode number has associated experimental data
1261 tempI = ((Integer)arraylTE.get(arraylHeaderIndex)).intValue();
1262 testVec++;
1263 if(tempI>0){
1264 modeType[atCurveNumber] = "TE";
1265 modeType[atCurveNumber+1] = "TE";
1266 modeNumber[atCurveNumber] = ((Integer)arraylTE.get(arraylHeaderIndex-1)).intValue();
1267 modeNumber[atCurveNumber+1] = modeNumber[atCurveNumber];
1268 testVec++;
1269
1270 // experimental data curve
1271 double[] tempThick = new double[tempI];
1272 double[] tempRefra = new double[tempI];
1273 for(int i=0; i<tempI; i++){
1274 tempThick[i] = ((Double)arraylTE.get(arraylIndex++)).doubleValue();
1275 tempRefra[i] = ((Double)arraylTE.get(arraylIndex++)).doubleValue();
1276 testVec += 2;
1277 }
1278 double[] log10TempThick = Conv.copy(tempThick);
1279 for(int i=0; i<tempI; i++)log10TempThick[i] = Fmath.log10(tempThick[i]);
1280
1281 plotData[plotNumber++] = log10TempThick;
1282 plotData[plotNumber++] = tempRefra;
1283
1284 // sort into ascending thicknesses
1285 Fmath.selectionSort(tempThick, tempRefra, tempThick, tempRefra);
1286
1287 // calculated curve
1288 double[][] curveTE = dispersionCurveTE(tempThick[0], tempThick[tempI-1], maximumNumberOfPoints, modeNumber[atCurveNumber]);
1289 plotData[plotNumber++] = curveTE[0];
1290 plotData[plotNumber++] = curveTE[1];
1291
1292 atCurveNumber += 2;
1293 }
1294 arraylHeaderIndex =+ 2;
1295 }
1296 }
1297
1298 // TM mode curves
1299 arraylIndex = 2*(pOrdersCheckedTM+1);
1300 arraylHeaderIndex = 1;
1301 tempD = 0.0D;
1302 tempI = 0;
1303
1304 if(this.numberOfTMmeasurements>0){
1305 int testVec = 0;
1306 int arraylSize = arraylTM.size();
1307 while(testVec<arraylSize){
1308 // Check mode number has associated experimental data
1309 tempI = ((Integer)arraylTM.get(arraylHeaderIndex)).intValue();
1310 testVec++;
1311 if(tempI>0){
1312 modeType[atCurveNumber] = "TM";
1313 modeType[atCurveNumber+1] = "TM";
1314 modeNumber[atCurveNumber] = ((Integer)arraylTM.get(arraylHeaderIndex-1)).intValue();
1315 testVec++;
1316 modeNumber[atCurveNumber+1] = modeNumber[atCurveNumber];
1317
1318 // experimental data curve
1319 double[] tempThick = new double[tempI];
1320 double[] tempRefra = new double[tempI];
1321 for(int i=0; i<tempI; i++){
1322 tempThick[i] = ((Double)arraylTM.get(arraylIndex++)).doubleValue();
1323 tempRefra[i] = ((Double)arraylTM.get(arraylIndex++)).doubleValue();
1324 testVec += 2;
1325 }
1326 double[] log10TempThick = Conv.copy(tempThick);
1327 for(int i=0; i<tempI; i++)log10TempThick[i] = Fmath.log10(tempThick[i]);
1328
1329 plotData[plotNumber++] = log10TempThick;
1330 plotData[plotNumber++] = tempRefra;
1331
1332 // sort into ascending thicknesses
1333 Fmath.selectionSort(tempThick, tempRefra, tempThick, tempRefra);
1334
1335 // calculated curve
1336 double[][] curveTM = dispersionCurveTM(tempThick[0], tempThick[tempI-1], maximumNumberOfPoints, modeNumber[atCurveNumber]);
1337 plotData[plotNumber++] = curveTM[0];
1338 plotData[plotNumber++] = curveTM[1];
1339
1340 atCurveNumber += 2;
1341 }
1342 arraylHeaderIndex =+ 2;
1343 }
1344 }
1345
1346 // Create instance of PlotGraph
1347 PlotGraph pg0 = new PlotGraph(plotData);
1348
1349 int[] lineOptions = new int[numberOfCurves];
1350 for(int i=0; i<numberOfCurves; i+=2){
1351 lineOptions[i] = 0;
1352 lineOptions[i+1] = 3;
1353 if(maximumNumberOfPoints<100)lineOptions[i+1] = 1;
1354 }
1355 pg0.setLine(lineOptions);
1356
1357 int[] pointOptions = new int[numberOfCurves];
1358 int jj = 1;
1359 for(int i=0; i<numberOfCurves; i+=2){
1360 pointOptions[i] = jj;
1361 pointOptions[i+1] = 0;
1362 jj++;
1363 }
1364 pg0.setPoint(pointOptions);
1365
1366 pg0.setGraphTitle(legend);
1367 pg0.setXaxisLegend("Log10( Core Film Thickness / metres )");
1368 pg0.setYaxisLegend("Effective Refractive Index (kz/ko)");
1369
1370 // Plot graphs
1371 pg0.plot();
1372 }
1373
1374 // CALCULATION OF THE SUPERSTRATE REFRACTIVE INDEX
1375 public void calcSuperstrateRefractiveIndex(){
1376 if(!this.setMeasurements)throw new IllegalArgumentException("Either no thickness, angle/effective refractive index, mode number data has been entered or a key subclass variable, e.g. coupling prism corner angle has not been entered");
1377 if(!this.setWavelength)throw new IllegalArgumentException("No wavelength has been entered");
1378 if(!this.setSubstrate)throw new IllegalArgumentException("No substrate refractive index has been entered");
1379 if(!this.setCore)throw new IllegalArgumentException("No core layer refractive index has been entered");
1380
1381 // Set the bounds and eliminate points where effective ref. index < substrate or superstrate ref. index
1382 this.lowerBound = 1.0D;
1383 this.upperBound = this.coreFilmRefractiveIndex;
1384
1385 if(this.numberOfTEmeasurements>0)this.eliminatedTE = new boolean[this.numberOfTEmeasurements];
1386 int elimNumberTE = 0;
1387 for(int i=0; i<this.numberOfTEmeasurements; i++){
1388 this.eliminatedTE[i] = false;
1389 if(this.measurementsTE[i][1]>this.coreFilmRefractiveIndex){
1390 System.out.println("TE mode measurement point, " + i + ", eliminated as the effective refractive index, " + this.measurementsTE[i][1] + ", lies above the physical limit, " + this.coreFilmRefractiveIndex);
1391 this.eliminatedTE[i] = true;
1392 elimNumberTE++;
1393 }
1394 else{
1395 if(this.upperBound>this.measurementsTE[i][1])this.upperBound = this.measurementsTE[i][1];
1396 }
1397 }
1398 if(elimNumberTE>0){
1399 int newNumber = this.numberOfTEmeasurements - elimNumberTE;
1400 if(newNumber==0){
1401 this.numberOfTEmeasurements = 0;
1402 }
1403 else{
1404 double[][] temp = new double[newNumber][3];
1405 int nIndex = 0;
1406 for(int i=0; i<this.numberOfTEmeasurements; i++){
1407 if(!this.eliminatedTE[i]){
1408 temp[nIndex][0] = this.measurementsTE[i][0];
1409 temp[nIndex][1] = this.measurementsTE[i][1];
1410 temp[nIndex][2] = this.measurementsTE[i][2];
1411 temp[nIndex][3] = this.measurementsTE[i][3];
1412 nIndex++;
1413 }
1414 }
1415 this.measurementsTE = temp;
1416 this.numberOfTEmeasurements = newNumber;
1417 this.numberOfMeasurements = this.numberOfTEmeasurements + this.numberOfTMmeasurements;
1418 }
1419 }
1420 this.thicknessesUsedTE = new double[this.numberOfTEmeasurements];
1421 this.calcEffectRefrIndicesTE = new double[this.numberOfTEmeasurements];
1422 for(int i=0; i<this.numberOfTEmeasurements; i++)this.thicknessesUsedTE[i] = this.measurementsTE[i][0];
1423 this.minimumTEmodeEffectiveRefractiveIndex = this.upperBound;
1424
1425 this.upperBound = 0.0D;
1426 if(this.numberOfTMmeasurements>0)this.eliminatedTM = new boolean[this.numberOfTMmeasurements];
1427 int elimNumberTM = 0;
1428 for(int i=0; i<this.numberOfTMmeasurements; i++){
1429 this.eliminatedTM[i] = false;
1430 if(this.measurementsTM[i][1]>this.coreFilmRefractiveIndex){
1431 System.out.println("TM mode measurement point, " + i + ", eliminated as the effective refractive index, " + this.measurementsTM[i][1] + ", lies above the physical limit, " + this.coreFilmRefractiveIndex);
1432 this.eliminatedTM[i] = true;
1433 elimNumberTM++;
1434 }
1435 else{
1436 if(this.upperBound>this.measurementsTM[i][1])this.upperBound = this.measurementsTM[i][1];
1437 }
1438 }
1439 if(elimNumberTM>0){
1440 int newNumber = this.numberOfTMmeasurements - elimNumberTM;
1441 if(newNumber==0){
1442 this.numberOfTMmeasurements = 0;
1443 }
1444 else{
1445 double[][] temp = new double[newNumber][3];
1446 int nIndex = 0;
1447 for(int i=0; i<this.numberOfTMmeasurements; i++){
1448 if(!this.eliminatedTM[i]){
1449 temp[nIndex][0] = this.measurementsTM[i][0];
1450 temp[nIndex][1] = this.measurementsTM[i][1];
1451 temp[nIndex][2] = this.measurementsTM[i][2];
1452 temp[nIndex][3] = this.measurementsTM[i][3];
1453 nIndex++;
1454 }
1455 }
1456 this.measurementsTM = temp;
1457 this.numberOfTMmeasurements = newNumber;
1458 this.numberOfMeasurements = this.numberOfTEmeasurements + this.numberOfTMmeasurements;
1459 }
1460 }
1461 this.thicknessesUsedTM = new double[this.numberOfTMmeasurements];
1462 this.calcEffectRefrIndicesTM = new double[this.numberOfTMmeasurements];
1463 for(int i=0; i<this.numberOfTMmeasurements; i++)this.thicknessesUsedTM[i] = this.measurementsTM[i][0];
1464 this.minimumTMmodeEffectiveRefractiveIndex = this.upperBound;
1465
1466 if(this.numberOfMeasurements==0)throw new IllegalArgumentException("All data points rejected as lying outside the physically meaningful bounds");
1467
1468 // call the root search methods to obtain the superstrate refractive index/indices
1469 if(this.numberOfTEmeasurements>0)this.calcTEmodeSuperstrateRefractiveIndices();
1470 if(this.numberOfTMmeasurements>0)this.calcTMmodeSuperstrateRefractiveIndices();
1471
1472 // Calculate the overall mean and standard deviation of the superstrate refractive index
1473 if(this.numberOfTEmeasurements>0 && this.numberOfTMmeasurements==0){
1474 this.superstrateRefractiveIndex = this.meanTEmodeSuperstrateRefractiveIndex;
1475 this.sdSuperstrateRefractiveIndex = this.sdTEmodeSuperstrateRefractiveIndex;
1476 }
1477 else{
1478 if(this.numberOfTMmeasurements>0 && this.numberOfTEmeasurements==0){
1479 this.superstrateRefractiveIndex = this.meanTMmodeSuperstrateRefractiveIndex;
1480 this.sdSuperstrateRefractiveIndex = this.sdTMmodeSuperstrateRefractiveIndex;
1481 }
1482 else{
1483 double[] values = new double[this.numberOfMeasurements];
1484 double[] weights = new double[this.numberOfMeasurements];
1485 for(int i=0; i<this.numberOfTEmeasurements; i++){
1486 values[i] = this.calcSuperstrateTEmodeRI[i];
1487 weights[i] = this.measurementsTE[i][2];
1488 }
1489 for(int i=0; i<this.numberOfTMmeasurements; i++){
1490 values[i+this.numberOfTEmeasurements] = this.calcSuperstrateTMmodeRI[i];
1491 weights[i+this.numberOfTEmeasurements] = this.measurementsTM[i][2];
1492 }
1493 this.superstrateRefractiveIndex = Stat.mean(values, weights);
1494 this.sdSuperstrateRefractiveIndex = Stat.standardDeviation(values, weights);
1495 }
1496 }
1497
1498 this.superstrateRefractiveIndex2 = this.superstrateRefractiveIndex*this.superstrateRefractiveIndex;
1499 this.minimumEffectiveRefractiveIndex = Math.min(this.minimumTEmodeEffectiveRefractiveIndex, this.minimumTMmodeEffectiveRefractiveIndex);
1500 this.superCalculationDone = true;
1501 }
1502
1503 // Calculate TE mode refractive indices
1504 public void calcTEmodeSuperstrateRefractiveIndices(){
1505
1506 this.calcSuperstrateTEmodeRI = new double[this.numberOfTEmeasurements];
1507
1508 // Create instance of the class holding the TE mode core film refractive indexfunction
1509 FunctTEsuper func = new FunctTEsuper();
1510
1511 // Set function parameters
1512 func.coreFilmRefractiveIndex2 = this.coreFilmRefractiveIndex2;
1513 func.ko = this.ko;
1514
1515 double[] weights = new double[this.numberOfTEmeasurements];
1516 this.lowerBound = 1.0D;
1517 this.upperBound = this.minimumTEmodeEffectiveRefractiveIndex;
1518
1519 for(int i=0; i<this.numberOfTEmeasurements; i++){
1520 weights[i] = this.measurementsTE[i][2];
1521
1522 // set further function parameters
1523 func.thickness = this.measurementsTE[i][0];
1524 func.effectiveRefractiveIndex2 = this.measurementsTE[i][1]*this.measurementsTE[i][1];
1525 func.modeNumber = this.measurementsTE[i][3];
1526
1527 // call root searching method, bisection, to obtain core refractive index
1528 RealRoot rr = new RealRoot();
1529 rr.noBoundsExtensions();
1530 rr.setTolerance(this.tolerance);
1531 this.calcSuperstrateTEmodeRI[i] = rr.bisect(func, this.lowerBound, this.upperBound);
1532 }
1533
1534 // Calculate mean and sd
1535 if(this.numberOfTEmeasurements>1){
1536 this.meanTEmodeSuperstrateRefractiveIndex = Stat.mean(this.calcSuperstrateTEmodeRI, weights);
1537 this.sdTEmodeSuperstrateRefractiveIndex = Stat.standardDeviation(this.calcSuperstrateTEmodeRI, weights);
1538 }
1539 else{
1540 this.meanTEmodeSuperstrateRefractiveIndex = this.calcSuperstrateTEmodeRI[0];
1541 }
1542 }
1543
1544 // Calculate TM mode refractive indices
1545 public void calcTMmodeSuperstrateRefractiveIndices(){
1546
1547 this.calcSuperstrateTMmodeRI = new double[this.numberOfTMmeasurements];
1548
1549 // Create instance of the class holding the TM mode core film refractive indexfunction
1550 FunctTMsuper func = new FunctTMsuper();
1551
1552 // Set function parameters
1553 func.coreFilmRefractiveIndex2 = this.coreFilmRefractiveIndex2;
1554 func.ko = this.ko;
1555
1556 double[] weights = new double[this.numberOfTMmeasurements];
1557 this.lowerBound = 1.0D;
1558 this.upperBound = this.minimumTMmodeEffectiveRefractiveIndex;
1559
1560 for(int i=0; i<this.numberOfTMmeasurements; i++){
1561 weights[i] = this.measurementsTM[i][2];
1562
1563 // set further function parameters
1564 func.thickness = this.measurementsTM[i][0];
1565 func.effectiveRefractiveIndex2 = this.measurementsTM[i][1]*this.measurementsTM[i][1];
1566 func.modeNumber = this.measurementsTM[i][3];
1567
1568 // call root searching method, bisection, to obtain core refractive index
1569 RealRoot rr = new RealRoot();
1570 rr.noBoundsExtensions();
1571 rr.setTolerance(this.tolerance);
1572 this.calcSuperstrateTMmodeRI[i] = rr.bisect(func, this.lowerBound, this.upperBound);
1573 }
1574
1575 // Calculate mean and sd
1576 if(this.numberOfTMmeasurements>1){
1577 this.meanTMmodeSuperstrateRefractiveIndex = Stat.mean(this.calcSuperstrateTMmodeRI, weights);
1578 this.sdTMmodeSuperstrateRefractiveIndex = Stat.standardDeviation(this.calcSuperstrateTMmodeRI, weights);
1579 }
1580 else{
1581 this.meanTMmodeSuperstrateRefractiveIndex = this.calcSuperstrateTMmodeRI[0];
1582 }
1583 }
1584}
1585
1586// Class containing function with the root search for the TE mode core film refractive index
1587class FunctTE implements RealRootFunction{
1588
1589 public double substrateRefractiveIndex2 = 0.0D;
1590 public double superstrateRefractiveIndex2 = 0.0D;
1591 public double effectiveRefractiveIndex2 = 0.0D;
1592 public double prismRefractiveIndex2 = 0.0D;
1593 public double ko = 0.0D;
1594 public double prismToWaveguideGap = 0.0D;
1595 public boolean setPrismToWaveguideGap = false;
1596 public double thickness = 0.0D;
1597 public double modeNumber = 0;
1598
1599 public double function(double x){
1600 double y = 0.0D;
1601
1602 // function calculation
1603 double coreFilmRefractiveIndex2 = x*x;
1604 double zetaSub = Math.sqrt(this.effectiveRefractiveIndex2 - this.substrateRefractiveIndex2);
1605 double zetaSuper = Math.sqrt(this.effectiveRefractiveIndex2 - this.superstrateRefractiveIndex2);
1606 double zetaFilm = Math.sqrt(coreFilmRefractiveIndex2 - this.effectiveRefractiveIndex2);
1607 double zetaPrism = Math.sqrt(this.prismRefractiveIndex2 - this.effectiveRefractiveIndex2);
1608 double gammaSuper = Math.atan2(zetaSuper, zetaFilm);
1609 y = Math.PI*modeNumber - this.thickness*this.ko*zetaFilm;
1610 y += (gammaSuper + Math.atan2(zetaSub, zetaFilm));
1611 if(this.setPrismToWaveguideGap) y += (Math.sin(gammaSuper)*Math.cos( Math.atan2(zetaSuper, zetaPrism))*Math.exp(-2.0D*this.prismToWaveguideGap*this.ko*zetaSuper));
1612
1613 return y;
1614 }
1615}
1616
1617// Class containing function with the root search for the TM mode core film refractive index
1618class FunctTM implements RealRootFunction{
1619
1620 public double substrateRefractiveIndex2 = 0.0D;
1621 public double superstrateRefractiveIndex2 = 0.0D;
1622 public double effectiveRefractiveIndex2 = 0.0D;
1623 public double prismRefractiveIndex2 = 0.0D;
1624 public double ko = 0.0D;
1625 public double prismToWaveguideGap = 0.0D;
1626 public boolean setPrismToWaveguideGap = false;
1627 public double thickness = 0.0D;
1628 public double modeNumber = 0;
1629
1630 public double function(double x){
1631 double y = 0.0D;
1632
1633 // function calculation
1634 double coreFilmRefractiveIndex2 = x*x;
1635 double zetaSub = Math.sqrt(this.effectiveRefractiveIndex2 - this.substrateRefractiveIndex2);
1636 double zetaSuper = Math.sqrt(this.effectiveRefractiveIndex2 - this.superstrateRefractiveIndex2);
1637 double zetaFilm = Math.sqrt(coreFilmRefractiveIndex2 - this.effectiveRefractiveIndex2);
1638 double zetaPrism = Math.sqrt(this.prismRefractiveIndex2 - this.effectiveRefractiveIndex2);
1639 double gammaSuper = Math.atan2(coreFilmRefractiveIndex2*zetaSuper, this.superstrateRefractiveIndex2*zetaFilm);
1640 y = Math.PI*modeNumber - this.thickness*this.ko*zetaFilm;
1641 y += (gammaSuper + Math.atan2(coreFilmRefractiveIndex2*zetaSub, this.substrateRefractiveIndex2*zetaFilm));
1642 if(this.setPrismToWaveguideGap) y += (Math.sin(gammaSuper)*Math.cos( Math.atan2(zetaSuper*this.prismRefractiveIndex2, zetaPrism*this.superstrateRefractiveIndex2))*Math.exp(-2.0D*this.prismToWaveguideGap*zetaSuper));
1643
1644 return y;
1645 }
1646}
1647
1648// Class containing function with the root search for the TE mode effective refractive index
1649class FunctTEplot implements RealRootFunction{
1650
1651 public double substrateRefractiveIndex2 = 0.0D;
1652 public double superstrateRefractiveIndex2 = 0.0D;
1653 public double coreFilmRefractiveIndex2 = 0.0D;
1654 public double prismRefractiveIndex2 = 0.0D;
1655 public double ko = 0.0D;
1656 public double prismToWaveguideGap = 0.0D;
1657 public boolean setPrismToWaveguideGap = false;
1658 public double thickness = 0.0D;
1659 public double modeNumber = 0;
1660
1661 public double function(double x){
1662 double y = 0.0D;
1663
1664 // function calculation
1665 double effectiveRefractiveIndex2 = x*x;
1666 double zetaSub = Math.sqrt(effectiveRefractiveIndex2 - this.substrateRefractiveIndex2);
1667 double zetaSuper = Math.sqrt(effectiveRefractiveIndex2 - this.superstrateRefractiveIndex2);
1668 double zetaFilm = Math.sqrt(this.coreFilmRefractiveIndex2 - effectiveRefractiveIndex2);
1669 double zetaPrism = Math.sqrt(this.prismRefractiveIndex2 - effectiveRefractiveIndex2);
1670 double gammaSuper = Math.atan2(zetaSuper, zetaFilm);
1671 y = Math.PI*modeNumber - this.thickness*this.ko*zetaFilm;
1672 y += (gammaSuper + Math.atan2(zetaSub, zetaFilm));
1673 if(this.setPrismToWaveguideGap) y += (Math.sin(gammaSuper)*Math.cos( Math.atan2(zetaSuper, zetaPrism))*Math.exp(-2.0D*this.prismToWaveguideGap*this.ko*zetaSuper));
1674
1675 return y;
1676 }
1677}
1678
1679// Class containing function with the root search for the TM mode effective refractive index
1680class FunctTMplot implements RealRootFunction{
1681
1682 public double substrateRefractiveIndex2 = 0.0D;
1683 public double superstrateRefractiveIndex2 = 0.0D;
1684 public double coreFilmRefractiveIndex2 = 0.0D;
1685 public double prismRefractiveIndex2 = 0.0D;
1686 public double ko = 0.0D;
1687 public double prismToWaveguideGap = 0.0D;
1688 public boolean setPrismToWaveguideGap = false;
1689 public double thickness = 0.0D;
1690 public double modeNumber = 0;
1691
1692 public double function(double x){
1693 double y = 0.0D;
1694
1695 double effectiveRefractiveIndex2 = x*x;
1696 double zetaSub = Math.sqrt(effectiveRefractiveIndex2 - this.substrateRefractiveIndex2);
1697 double zetaSuper = Math.sqrt(effectiveRefractiveIndex2 - this.superstrateRefractiveIndex2);
1698 double zetaFilm = Math.sqrt(this.coreFilmRefractiveIndex2 - effectiveRefractiveIndex2);
1699 double zetaPrism = Math.sqrt(this.prismRefractiveIndex2 - effectiveRefractiveIndex2);
1700 double gammaSuper = Math.atan2(this.coreFilmRefractiveIndex2*zetaSuper, this.superstrateRefractiveIndex2*zetaFilm);
1701 y = Math.PI*modeNumber - this.thickness*this.ko*zetaFilm;
1702 y += (gammaSuper + Math.atan2(this.coreFilmRefractiveIndex2*zetaSub, this.substrateRefractiveIndex2*zetaFilm));
1703 if(this.setPrismToWaveguideGap) y += (Math.sin(gammaSuper)*Math.cos( Math.atan2(zetaSuper*this.prismRefractiveIndex2, zetaPrism*this.superstrateRefractiveIndex2))*Math.exp(-2.0D*this.prismToWaveguideGap*zetaSuper));
1704
1705 return y;
1706 }
1707}
1708
1709// Class containing function with the root search for the TE mode superstrate refractive index
1710class FunctTEsuper implements RealRootFunction{
1711
1712 public double substrateRefractiveIndex2 = 0.0D;
1713 public double effectiveRefractiveIndex2 = 0.0D;
1714 public double coreFilmRefractiveIndex2 = 0.0D;
1715 public double ko = 0.0D;
1716 public double thickness = 0.0D;
1717 public double modeNumber = 0;
1718
1719 public double function(double x){
1720 double y = 0.0D;
1721
1722 // function calculation
1723 double superstrateRefractiveIndex2 = x*x;
1724 double zetaSub = Math.sqrt(this.effectiveRefractiveIndex2 - this.substrateRefractiveIndex2);
1725 double zetaSuper = Math.sqrt(effectiveRefractiveIndex2 - superstrateRefractiveIndex2);
1726 double zetaFilm = Math.sqrt(this.coreFilmRefractiveIndex2 - this.effectiveRefractiveIndex2);
1727 y = Math.PI*modeNumber - this.thickness*this.ko*zetaFilm;
1728 y += (Math.atan2(zetaSuper, zetaFilm) + Math.atan2(zetaSub, zetaFilm));
1729
1730 return y;
1731 }
1732}
1733
1734// Class containing function with the root search for the TM mode superstrate refractive index
1735class FunctTMsuper implements RealRootFunction{
1736
1737 public double substrateRefractiveIndex2 = 0.0D;
1738 public double effectiveRefractiveIndex2 = 0.0D;
1739 public double coreFilmRefractiveIndex2 = 0.0D;
1740 public double ko = 0.0D;
1741 public double thickness = 0.0D;
1742 public double modeNumber = 0;
1743
1744 public double function(double x){
1745 double y = 0.0D;
1746
1747 double superstrateRefractiveIndex2 = x*x;
1748 double zetaSub = Math.sqrt(this.effectiveRefractiveIndex2 - this.substrateRefractiveIndex2);
1749 double zetaSuper = Math.sqrt(effectiveRefractiveIndex2 - superstrateRefractiveIndex2);
1750 double zetaFilm = Math.sqrt(this.coreFilmRefractiveIndex2 - this.effectiveRefractiveIndex2);
1751 y = Math.PI*modeNumber - this.thickness*this.ko*zetaFilm;
1752 y += (Math.atan2(this.coreFilmRefractiveIndex2*zetaSuper, superstrateRefractiveIndex2*zetaFilm) + Math.atan2(this.coreFilmRefractiveIndex2*zetaSub, this.substrateRefractiveIndex2*zetaFilm));
1753
1754 return y;
1755 }
1756}
Note: See TracBrowser for help on using the repository browser.