]> git.mxchange.org Git - flightgear.git/blob - src/FDM/JSBSim/FGTable.cpp
Fix stall widths for the "auxilliary" (reverse flow) stalls so they
[flightgear.git] / src / FDM / JSBSim / FGTable.cpp
1 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2
3  Module:       FGTable.cpp
4  Author:       Jon S. Berndt
5  Date started: 1/9/2001
6  Purpose:      Models a lookup table
7
8  ------------- Copyright (C) 2001  Jon S. Berndt (jsb@hal-pc.org) -------------
9
10  This program is free software; you can redistribute it and/or modify it under
11  the terms of the GNU General Public License as published by the Free Software
12  Foundation; either version 2 of the License, or (at your option) any later
13  version.
14
15  This program is distributed in the hope that it will be useful, but WITHOUT
16  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
17  FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
18  details.
19
20  You should have received a copy of the GNU General Public License along with
21  this program; if not, write to the Free Software Foundation, Inc., 59 Temple
22  Place - Suite 330, Boston, MA  02111-1307, USA.
23
24  Further information about the GNU General Public License can also be found on
25  the world wide web at http://www.gnu.org.
26
27 FUNCTIONAL DESCRIPTION
28 --------------------------------------------------------------------------------
29 Models a lookup table
30
31 HISTORY
32 --------------------------------------------------------------------------------
33 JSB  1/9/00          Created
34
35 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
36 INCLUDES
37 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
38
39 #include "FGTable.h"
40
41 #if defined ( sgi ) && !defined( __GNUC__ ) && (_COMPILER_VERSION < 740)
42 #include <iomanip.h>
43 #else
44 #include <iomanip>
45 #endif
46
47 using namespace std;
48
49 namespace JSBSim {
50
51 static const char *IdSrc = "$Id$";
52 static const char *IdHdr = ID_TABLE;
53
54 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
55 CLASS IMPLEMENTATION
56 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
57
58
59 FGTable::FGTable(int NRows, int NCols, int NTables)
60                                  : nRows(NTables), nCols(1), nTables(NTables)
61 {
62   Type = tt3D;
63   colCounter = 1;
64   rowCounter = 1;
65
66   Data = Allocate(); // this data array will contain the keys for the associated tables
67   Tables.reserve(nTables);
68   for (int i=0; i<nTables; i++) Tables.push_back(FGTable(NRows, NCols));
69   lastRowIndex=lastColumnIndex=2;
70
71   Debug(0);
72 }
73
74 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
75
76 FGTable::FGTable(int NRows, int NCols) : nRows(NRows), nCols(NCols)
77 {
78   if (NCols > 1) {
79     Type = tt2D;
80     colCounter = 1;
81     rowCounter = 0;
82   } else if (NCols == 1) {
83     Type = tt1D;
84     colCounter = 0;
85     rowCounter = 1;
86   } else {
87     cerr << "FGTable cannot accept 'Rows=0'" << endl;
88   }
89
90   Data = Allocate();
91   lastRowIndex=lastColumnIndex=2;
92   Debug(0);
93 }
94
95 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
96
97 FGTable::FGTable(int NRows) : nRows(NRows), nCols(1)
98 {
99   Type = tt1D;
100   colCounter = 0;
101   rowCounter = 1;
102
103   Data = Allocate();
104   Debug(0);
105   lastRowIndex=lastColumnIndex=2;
106 }
107
108 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
109
110 FGTable::FGTable(const FGTable& t)
111 {
112   Type = t.Type;
113   colCounter = t.colCounter;
114   rowCounter = t.rowCounter;
115   tableCounter = t.tableCounter;
116
117   nRows = t.nRows;
118   nCols = t.nCols;
119   nTables = t.nTables;
120
121   Tables = t.Tables;
122   Data = Allocate();
123   for (int r=0; r<=nRows; r++) {
124     for (int c=0; c<=nCols; c++) {
125       Data[r][c] = t.Data[r][c];
126     }
127   }
128   lastRowIndex = t.lastRowIndex;
129   lastColumnIndex = t.lastColumnIndex;
130   lastTableIndex = t.lastTableIndex;
131 }
132
133 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
134
135 double** FGTable::Allocate(void)
136 {
137   Data = new double*[nRows+1];
138   for (int r=0; r<=nRows; r++) {
139     Data[r] = new double[nCols+1];
140     for (int c=0; c<=nCols; c++) {
141       Data[r][c] = 0.0;
142     }
143   }
144   return Data;
145 }
146
147 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
148
149 FGTable::~FGTable()
150 {
151   if (nTables > 0) Tables.clear();
152   for (int r=0; r<=nRows; r++) if (Data[r]) delete[] Data[r];
153   if (Data) delete[] Data;
154   Debug(1);
155 }
156
157 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
158
159 double FGTable::GetValue(double key)
160 {
161   double Factor, Value, Span;
162   int r=lastRowIndex;
163
164   //if the key is off the end of the table, just return the
165   //end-of-table value, do not extrapolate
166   if( key <= Data[1][0] ) {
167     lastRowIndex=2;
168     //cout << "Key underneath table: " << key << endl;
169     return Data[1][1];
170   } else if ( key >= Data[nRows][0] ) {
171     lastRowIndex=nRows;
172     //cout << "Key over table: " << key << endl;
173     return Data[nRows][1];
174   }
175
176   // the key is somewhere in the middle, search for the right breakpoint
177   // assume the correct breakpoint has not changed since last frame or
178   // has only changed very little
179
180   if ( r > 2 && Data[r-1][0] > key ) {
181     while( Data[r-1][0] > key && r > 2) { r--; }
182   } else if ( Data[r][0] < key ) {
183     while( Data[r][0] <= key && r <= nRows) { r++; }
184   }
185
186   lastRowIndex=r;
187   // make sure denominator below does not go to zero.
188
189   Span = Data[r][0] - Data[r-1][0];
190   if (Span != 0.0) {
191     Factor = (key - Data[r-1][0]) / Span;
192     if (Factor > 1.0) Factor = 1.0;
193   } else {
194     Factor = 1.0;
195   }
196
197   Value = Factor*(Data[r][1] - Data[r-1][1]) + Data[r-1][1];
198
199   return Value;
200 }
201
202 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
203
204
205 double FGTable::GetValue(double rowKey, double colKey)
206 {
207   double rFactor, cFactor, col1temp, col2temp, Value;
208   int r=lastRowIndex;
209   int c=lastColumnIndex;
210
211   if ( r > 2 && Data[r-1][0] > rowKey ) {
212     while ( Data[r-1][0] > rowKey && r > 2) { r--; }
213   } else if ( Data[r][0] < rowKey ) {
214 //    cout << Data[r][0] << endl;
215     while ( r <= nRows && Data[r][0] <= rowKey ) { r++; }
216     if ( r > nRows ) r = nRows;
217   }
218
219   if ( c > 2 && Data[0][c-1] > colKey ) {
220     while( Data[0][c-1] > colKey && c > 2) { c--; }
221   } else if ( Data[0][c] < colKey ) {
222     while( Data[0][c] <= colKey && c <= nCols) { c++; }
223     if ( c > nCols ) c = nCols;
224   }
225
226   lastRowIndex=r;
227   lastColumnIndex=c;
228
229   rFactor = (rowKey - Data[r-1][0]) / (Data[r][0] - Data[r-1][0]);
230   cFactor = (colKey - Data[0][c-1]) / (Data[0][c] - Data[0][c-1]);
231
232   if (rFactor > 1.0) rFactor = 1.0;
233   else if (rFactor < 0.0) rFactor = 0.0;
234
235   if (cFactor > 1.0) cFactor = 1.0;
236   else if (cFactor < 0.0) cFactor = 0.0;
237
238   col1temp = rFactor*(Data[r][c-1] - Data[r-1][c-1]) + Data[r-1][c-1];
239   col2temp = rFactor*(Data[r][c] - Data[r-1][c]) + Data[r-1][c];
240
241   Value = col1temp + cFactor*(col2temp - col1temp);
242
243   return Value;
244 }
245
246 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
247
248 double FGTable::GetValue(double rowKey, double colKey, double tableKey)
249 {
250   double Factor, Value, Span;
251   int r=lastRowIndex;
252
253   //if the key is off the end  (or before the beginning) of the table,
254   // just return the boundary-table value, do not extrapolate
255
256   if( tableKey <= Data[1][1] ) {
257     lastRowIndex=2;
258     return Tables[0].GetValue(rowKey, colKey);
259   } else if ( tableKey >= Data[nRows][1] ) {
260     lastRowIndex=nRows;
261     return Tables[nRows-1].GetValue(rowKey, colKey);
262   }
263
264   // the key is somewhere in the middle, search for the right breakpoint
265   // assume the correct breakpoint has not changed since last frame or
266   // has only changed very little
267
268   if ( r > 2 && Data[r-1][1] > tableKey ) {
269     while( Data[r-1][1] > tableKey && r > 2) { r--; }
270   } else if ( Data[r][1] < tableKey ) {
271     while( Data[r][1] <= tableKey && r <= nRows) { r++; }
272   }
273
274   lastRowIndex=r;
275   // make sure denominator below does not go to zero.
276
277   Span = Data[r][1] - Data[r-1][1];
278   if (Span != 0.0) {
279     Factor = (tableKey - Data[r-1][1]) / Span;
280     if (Factor > 1.0) Factor = 1.0;
281   } else {
282     Factor = 1.0;
283   }
284
285   Value = Factor*(Tables[r-1].GetValue(rowKey, colKey) - Tables[r-2].GetValue(rowKey, colKey))
286                               + Tables[r-2].GetValue(rowKey, colKey);
287
288   return Value;
289 }
290
291 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
292
293 void FGTable::operator<<(FGConfigFile& infile)
294 {
295   int startRow=0;
296   int startCol=0;
297   int tableCtr=0;
298
299   if (Type == tt1D || Type == tt3D) startRow = 1;
300   if (Type == tt3D) startCol = 1;
301
302   for (int r=startRow; r<=nRows; r++) {
303     for (int c=startCol; c<=nCols; c++) {
304       if (r != 0 || c != 0) {
305         infile >> Data[r][c];
306         if (Type == tt3D) {
307           Tables[tableCtr] << infile;
308           tableCtr++;
309         }
310       }
311     }
312   }
313 }
314
315 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
316
317 FGTable& FGTable::operator<<(const double n)
318 {
319   Data[rowCounter][colCounter] = n;
320   if (colCounter == nCols) {
321     colCounter = 0;
322     rowCounter++;
323   } else {
324     colCounter++;
325   }
326   return *this;
327 }
328
329 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
330
331 FGTable& FGTable::operator<<(const int n)
332 {
333   *this << (double)n;
334   return *this;
335 }
336
337 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
338
339 void FGTable::Print(int spaces)
340 {
341   string tabspace;
342   int startRow=0;
343   int startCol=0;
344
345   if (Type == tt1D || Type == tt3D) startRow = 1;
346   if (Type == tt3D) startCol = 1;
347
348 #if defined (sgi) && !defined(__GNUC__) && (_COMPILER_VERSION < 740)
349   unsigned long flags = cout.setf(ios::fixed);
350 #else
351   ios::fmtflags flags = cout.setf(ios::fixed); // set up output stream
352 #endif
353
354   for (int i=0;i<spaces;i++) tabspace+=" ";
355
356   cout.precision(4);
357   for (int r=startRow; r<=nRows; r++) {
358     cout << tabspace;
359     for (int c=startCol; c<=nCols; c++) {
360       if (r == 0 && c == 0) {
361         cout << "       ";
362       } else {
363         cout << Data[r][c] << " ";
364         if (Type == tt3D) {
365           cout << endl;
366           Tables[r-1].Print(spaces);
367         }
368       }
369     }
370     cout << endl;
371   }
372   cout.setf(flags); // reset
373 }
374
375 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
376 //    The bitmasked value choices are as follows:
377 //    unset: In this case (the default) JSBSim would only print
378 //       out the normally expected messages, essentially echoing
379 //       the config files as they are read. If the environment
380 //       variable is not set, debug_lvl is set to 1 internally
381 //    0: This requests JSBSim not to output any messages
382 //       whatsoever.
383 //    1: This value explicity requests the normal JSBSim
384 //       startup messages
385 //    2: This value asks for a message to be printed out when
386 //       a class is instantiated
387 //    4: When this value is set, a message is displayed when a
388 //       FGModel object executes its Run() method
389 //    8: When this value is set, various runtime state variables
390 //       are printed out periodically
391 //    16: When set various parameters are sanity checked and
392 //       a message is printed out when they go out of bounds
393
394 void FGTable::Debug(int from)
395 {
396   if (debug_lvl <= 0) return;
397
398   if (debug_lvl & 1) { // Standard console startup message output
399     if (from == 0) { // Constructor
400
401     }
402   }
403   if (debug_lvl & 2 ) { // Instantiation/Destruction notification
404     if (from == 0) cout << "Instantiated: FGTable" << endl;
405     if (from == 1) cout << "Destroyed:    FGTable" << endl;
406   }
407   if (debug_lvl & 4 ) { // Run() method entry print for FGModel-derived objects
408   }
409   if (debug_lvl & 8 ) { // Runtime state variables
410   }
411   if (debug_lvl & 16) { // Sanity checking
412   }
413   if (debug_lvl & 64) {
414     if (from == 0) { // Constructor
415       cout << IdSrc << endl;
416       cout << IdHdr << endl;
417     }
418   }
419 }
420 }