source: src/main/java/agents/anac/y2015/agentBuyogV2/flanagan/interpolation/BiCubicSpline.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: 16.0 KB
Line 
1/**********************************************************
2*
3* BiCubicSpline.java
4*
5* Class for performing an interpolation on the tabulated
6* function y = f(x1,x2) using a natural bicubic spline
7* Assumes second derivatives at end points = 0 (natural spine)
8*
9* See BiCubicSplineFast.java for a faster running version
10* (http://www.ee.ucl.ac.uk/~mflanaga/java/BiCubicSplineFast.html)
11*
12* WRITTEN BY: Dr Michael Thomas Flanagan
13*
14* DATE: May 2002
15* UPDATE: 20 May 2003, 17 February 2006, 27 July 2007, 4 December 2007, 21 September 2008, 31 October 2009, 5 January 2011
16*
17* DOCUMENTATION:
18* See Michael Thomas Flanagan's Java library on-line web page:
19* http://www.ee.ucl.ac.uk/~mflanaga/java/BiCubicSpline.html
20* http://www.ee.ucl.ac.uk/~mflanaga/java/
21*
22* Copyright (c) 2003 - 2011 Michael Thomas Flanagan
23*
24* PERMISSION TO COPY:
25*
26* Permission to use, copy and modify this software and its documentation for NON-COMMERCIAL purposes is granted, without fee,
27* provided that an acknowledgement to the author, Dr Michael Thomas Flanagan at www.ee.ucl.ac.uk/~mflanaga, appears in all copies
28* and associated documentation or publications.
29*
30* 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
31* and the following disclaimer and requires written permission from the Michael Thomas Flanagan:
32*
33* Redistribution in binary form of all or parts of this class must reproduce the above copyright notice, this list of conditions and
34* the following disclaimer in the documentation and/or other materials provided with the distribution and requires written permission from the Michael Thomas Flanagan:
35*
36* Dr Michael Thomas Flanagan makes no representations about the suitability or fitness of the software for any or for a particular purpose.
37* Dr Michael Thomas Flanagan shall not be liable for any damages suffered as a result of using, modifying or distributing this software
38* or its derivatives.
39*
40***************************************************************************************/
41
42package agents.anac.y2015.agentBuyogV2.flanagan.interpolation;
43
44import agents.anac.y2015.agentBuyogV2.flanagan.math.Fmath;
45
46public class BiCubicSpline{
47
48 private int nPoints = 0; // no. of x1 tabulated points
49 private int mPoints = 0; // no. of x2 tabulated points
50 private int nPointsT = 0; // no. of transposed x1 tabulated points
51 private int mPointsT = 0; // no. of transposed x2 tabulated points
52 private double[][] y = null; // y=f(x1,x2) tabulated function
53 private double[][] yT = null; // transposed y=f(x1,x2) tabulated function, i.e. y=f(x2,x1)
54 private double[] x1 = null; // x1 in tabulated function f(x1,x2)
55 private double[] x2 = null; // x2 in tabulated function f(x1,x2)
56 private double xx1 = Double.NaN; // value of x1 at which an interpolated y value is required
57 private double xx2 = Double.NaN; // value of x2 at which an interpolated y value is required
58 private double[] xMin = new double[2]; // minimum values of x1 and x2
59 private double[] xMax = new double[2]; // maximum values of x1 and x2
60 private double[][] d2ydx2inner = null; // second derivatives of first called array of cubic splines
61 private double[][] d2ydx2innerT = null; // second derivatives of first called transposed array of cubic splines
62 private CubicSpline csn[] = null; // nPoints array of CubicSpline instances
63 private CubicSpline csm = null; // CubicSpline instance
64 private CubicSpline csnT[] = null; // mPoints array of transposed CubicSpline instances
65 private CubicSpline csmT = null; // transposed CubicSpline instance
66 private double interpolatedValue = Double.NaN; // interpolated value for the original 2D matrix
67 private double interpolatedValueTranspose = Double.NaN; // interpolated value for the transposed 2D matrix
68 private double interpolatedValueMean = Double.NaN; // mean interpolated value
69 private boolean derivCalculated = false; // = true when the first called cubic spline derivatives have been calculated
70 private boolean averageIdenticalAbscissae = false; // if true: the the ordinate values for identical abscissae are averaged
71 // If false: the abscissae values are separated by 0.001 of the total abscissae range;
72 private static double potentialRoundingError = 5e-15; // potential rounding error used in checking wheter a value lies within the interpolation bounds (static value)
73 private static boolean roundingCheck = true; // = true: points outside the interpolation bounds by less than the potential rounding error rounded to the bounds limit (static value)
74
75
76 // Constructor
77 // Constructor with data arrays initialised to arrays x and y
78 public BiCubicSpline(double[] x1, double[] x2, double[][] y){
79 this.nPoints=x1.length;
80 this.mPoints=x2.length;
81 this.nPointsT=this.mPoints;
82 this.mPointsT=this.nPoints;
83 if(this.nPoints!=y.length)throw new IllegalArgumentException("Arrays x1 and y-row are of different length " + this.nPoints + " " + y.length);
84 if(this.mPoints!=y[0].length)throw new IllegalArgumentException("Arrays x2 and y-column are of different length "+ this.mPoints + " " + y[0].length);
85 if(this.nPoints<3 || this.mPoints<3)throw new IllegalArgumentException("The data matrix must have a minimum size of 3 X 3");
86
87 this.csm = new CubicSpline(this.nPoints);
88 this.csn = CubicSpline.oneDarray(this.nPoints, this.mPoints);
89 this.csmT = new CubicSpline(this.mPoints);
90 this.csnT = CubicSpline.oneDarray(this.nPointsT, this.mPointsT);
91 this.x1 = new double[this.nPoints];
92 this.x2 = new double[this.mPoints];
93 this.y = new double[this.nPoints][this.mPoints];
94 this.yT = new double[this.nPointsT][this.mPointsT];
95 this.d2ydx2inner = new double[this.nPoints][this.mPoints];
96 this.d2ydx2innerT = new double[this.nPointsT][this.mPointsT];
97 for(int i=0; i<this.nPoints; i++){
98 this.x1[i]=x1[i];
99 }
100 this.xMin[0] = Fmath.minimum(this.x1);
101 this.xMax[0] = Fmath.maximum(this.x1);
102 for(int j=0; j<this.mPoints; j++){
103 this.x2[j]=x2[j];
104 }
105 this.xMin[1] = Fmath.minimum(this.x2);
106 this.xMax[1] = Fmath.maximum(this.x2);
107 for(int i =0; i<this.nPoints; i++){
108 for(int j=0; j<this.mPoints; j++){
109 this.y[i][j]=y[i][j];
110 }
111 }
112 for(int i =0; i<this.nPointsT; i++){
113 for(int j=0; j<this.mPointsT; j++){
114 this.yT[i][j]=y[j][i];
115 }
116 }
117
118 double[] yTempn = new double[mPoints];
119 for(int i=0; i<this.nPoints; i++){
120 for(int j=0; j<mPoints; j++)yTempn[j]=y[i][j];
121 this.csn[i].resetData(x2,yTempn);
122 this.csn[i].calcDeriv();
123 this.d2ydx2inner[i]=this.csn[i].getDeriv();
124 }
125
126 double[] yTempnT = new double[mPointsT];
127 for(int i=0; i<this.nPointsT; i++){
128 for(int j=0; j<mPointsT; j++)yTempnT[j]=yT[i][j];
129 this.csnT[i].resetData(x1,yTempnT);
130 this.csnT[i].calcDeriv();
131 this.d2ydx2innerT[i]=this.csnT[i].getDeriv();
132 }
133 this.derivCalculated = true;
134 }
135
136 // Constructor with data arrays initialised to zero
137 // Primarily for use by TriCubicSpline
138 public BiCubicSpline(int nP, int mP){
139 this.nPoints=nP;
140 this.mPoints=mP;
141 if(this.nPoints<3 || this.mPoints<3)throw new IllegalArgumentException("The data matrix must have a minimum size of 3 X 3");
142 this.nPointsT=mP;
143 this.mPointsT=nP;
144 this.csm = new CubicSpline(this.nPoints);
145 this.csmT = new CubicSpline(this.nPointsT);
146 if(!this.roundingCheck)this.csm.noRoundingErrorCheck();
147
148 this.csn = CubicSpline.oneDarray(this.nPoints, this.mPoints);
149 this.csnT = CubicSpline.oneDarray(this.nPointsT, this.mPointsT);
150
151 this.x1 = new double[this.nPoints];
152 this.x2 = new double[this.mPoints];
153 this.y = new double[this.nPoints][this.mPoints];
154 this.yT = new double[this.nPointsT][this.mPointsT];
155 this.d2ydx2inner = new double[this.nPoints][this.mPoints];
156 this.d2ydx2innerT = new double[this.nPointsT][this.mPointsT];
157
158 }
159
160 // METHODS
161
162 // Reset rounding error check option
163 // Default option: points outside the interpolation bounds by less than the potential rounding error rounded to the bounds limit
164 // This method causes this check to be ignored and an exception to be thrown if any point lies outside the interpolation bounds
165 public static void noRoundingErrorCheck(){
166 BiCubicSpline.roundingCheck = false;
167 CubicSpline.noRoundingErrorCheck();
168 }
169
170 // Reset potential rounding error value
171 // Default option: points outside the interpolation bounds by less than the potential rounding error rounded to the bounds limit
172 // The default value for the potential rounding error is 5e-15*times the 10^exponent of the value outside the bounds
173 // This method allows the 5e-15 to be reset
174 public static void potentialRoundingError(double potentialRoundingError){
175 BiCubicSpline.potentialRoundingError = potentialRoundingError;
176 CubicSpline.potentialRoundingError(potentialRoundingError);
177 }
178
179 // Reset the default handing of identical abscissae with different ordinates
180 // from the default option of separating the two relevant abscissae by 0.001 of the range
181 // to avraging the relevant ordinates
182 public void averageIdenticalAbscissae(){
183 this.averageIdenticalAbscissae = true;
184 for(int i=0; i<this.csn.length; i++)this.csn[i].averageIdenticalAbscissae();
185 this.csm.averageIdenticalAbscissae();
186 }
187
188 // Resets the x1, x2, y data arrays
189 // Primarily for use in TiCubicSpline
190 public void resetData(double[] x1, double[] x2, double[][] y){
191 if(x1.length!=y.length)throw new IllegalArgumentException("Arrays x1 and y row are of different length");
192 if(x2.length!=y[0].length)throw new IllegalArgumentException("Arrays x2 and y column are of different length");
193 if(this.nPoints!=x1.length)throw new IllegalArgumentException("Original array length not matched by new array length");
194 if(this.mPoints!=x2.length)throw new IllegalArgumentException("Original array length not matched by new array length");
195
196 for(int i=0; i<this.nPoints; i++){
197 this.x1[i]=x1[i];
198 }
199
200 for(int i=0; i<this.mPoints; i++){
201 this.x2[i]=x2[i];
202 }
203
204 for(int i=0; i<this.nPoints; i++){
205 for(int j=0; j<this.mPoints; j++){
206 this.y[i][j]=y[i][j];
207 this.yT[j][i]=y[i][j];
208 }
209 }
210
211 this.csm = new CubicSpline(this.nPoints);
212 this.csn = CubicSpline.oneDarray(this.nPoints, this.mPoints);
213 double[] yTempn = new double[mPoints];
214
215 for(int i=0; i<this.nPoints; i++){
216 for(int j=0; j<mPoints; j++)yTempn[j]=y[i][j];
217 this.csn[i].resetData(x2,yTempn);
218 this.csn[i].calcDeriv();
219 this.d2ydx2inner[i]=this.csn[i].getDeriv();
220 }
221
222 this.csmT = new CubicSpline(this.nPointsT);
223 this.csnT = CubicSpline.oneDarray(this.nPointsT, this.mPointsT);
224 double[] yTempnT = new double[mPointsT];
225
226 for(int i=0; i<this.nPointsT; i++){
227 for(int j=0; j<mPointsT; j++)yTempnT[j]=yT[i][j];
228 this.csnT[i].resetData(x1,yTempnT);
229 this.csnT[i].calcDeriv();
230 this.d2ydx2innerT[i]=this.csnT[i].getDeriv();
231 }
232
233 this.derivCalculated = true;
234
235 }
236
237 // Returns a new BiCubicSpline setting internal array size to nP x mP and all array values to zero with natural spline default
238 // Primarily for use in this.oneDarray for TiCubicSpline
239 public static BiCubicSpline zero(int nP, int mP){
240 if(nP<3 || mP<3)throw new IllegalArgumentException("A minimum of three x three data points is needed");
241 BiCubicSpline aa = new BiCubicSpline(nP, mP);
242 return aa;
243 }
244
245 // Create a one dimensional array of BiCubicSpline objects of length nP each of internal array size mP x lP
246 // Primarily for use in TriCubicSpline
247 public static BiCubicSpline[] oneDarray(int nP, int mP, int lP){
248 if(mP<3 || lP<3)throw new IllegalArgumentException("A minimum of three x three data points is needed");
249 BiCubicSpline[] a =new BiCubicSpline[nP];
250 for(int i=0; i<nP; i++){
251 a[i]=BiCubicSpline.zero(mP, lP);
252 }
253 return a;
254 }
255
256
257 // Get inner matrix of derivatives
258 // Primarily used by TriCubicSpline
259 public double[][] getDeriv(){
260 return this.d2ydx2inner;
261 }
262
263 // Get inner matrix of transpose derivatives
264 // Primarily used by TriCubicSpline
265 public double[][] getDerivTranspose(){
266 return this.d2ydx2innerT;
267 }
268
269
270 // Get minimum limits
271 public double[] getXmin(){
272 return this.xMin;
273 }
274
275 // Get maximum limits
276 public double[] getXmax(){
277 return this.xMax;
278 }
279
280 // Get limits to x
281 public double[] getLimits(){
282 double[] limits = {xMin[0], xMax[0], xMin[1], xMax[1]};
283 return limits;
284 }
285
286 // Display limits to x
287 public void displayLimits(){
288 System.out.println(" ");
289 for(int i=0; i<2; i++){
290 System.out.println("The limits to the x array " + i + " are " + xMin[i] + " and " + xMax[i]);
291 }
292 System.out.println(" ");
293 }
294
295 // Set inner matrix of derivatives
296 // Primarily used by TriCubicSpline
297 public void setDeriv(double[][] d2ydx2){
298 this.d2ydx2inner = d2ydx2;
299 this.derivCalculated = true;
300 }
301
302 // Set inner matrix of transpose derivatives
303 // Primarily used by TriCubicSpline
304 public void setDerivTranspose(double[][] d2ydx2){
305 this.d2ydx2innerT = d2ydx2;
306 this.derivCalculated = true;
307 }
308
309 // Returns an interpolated value of y for a value of x
310 // from a tabulated function y=f(x1,x2)
311 public double interpolate(double xx1, double xx2){
312
313 this.xx1 = xx1;
314 this.xx2 = xx2;
315
316 double[] yTempm = new double[this.nPoints];
317
318 for (int i=0;i<this.nPoints;i++){
319 yTempm[i]=this.csn[i].interpolate(xx2);
320 }
321 this.csm.resetData(x1,yTempm);
322 this.interpolatedValue = this.csm.interpolate(xx1);
323
324 double[] yTempmT = new double[this.nPointsT];
325
326 for (int i=0;i<this.nPointsT;i++){
327 yTempmT[i]=this.csnT[i].interpolate(xx1);
328 }
329 this.csmT.resetData(x2,yTempmT);
330 this.interpolatedValueTranspose = this.csmT.interpolate(xx2);
331
332 this.interpolatedValueMean = (this.interpolatedValue + this.interpolatedValueTranspose)/2.0;
333 return this.interpolatedValueMean;
334 }
335
336 // Returns mean interpolated value, interpolated value for data as entered, interpolated value for transposed matrix, xx1 value and xx2 value
337 public double[] getInterpolatedValues(){
338 double[] ret = {this.interpolatedValueMean, this.interpolatedValue, this.interpolatedValueTranspose, this.xx1, this.xx2};
339 return ret;
340 }
341
342
343
344}
345
Note: See TracBrowser for help on using the repository browser.