]> git.mxchange.org Git - flightgear.git/blob - src/FDM/JSBSim/math/FGTable.h
Merge branch 'jmt/units-fix' into maint
[flightgear.git] / src / FDM / JSBSim / math / FGTable.h
1 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2
3  Header:       FGTable.h
4  Author:       Jon S. Berndt
5  Date started: 1/9/2001
6
7  ------------- Copyright (C) 2001  Jon S. Berndt (jon@jsbsim.org) --------------
8
9  This program is free software; you can redistribute it and/or modify it under
10  the terms of the GNU Lesser General Public License as published by the Free Software
11  Foundation; either version 2 of the License, or (at your option) any later
12  version.
13
14  This program is distributed in the hope that it will be useful, but WITHOUT
15  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
16  FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more
17  details.
18
19  You should have received a copy of the GNU Lesser General Public License along with
20  this program; if not, write to the Free Software Foundation, Inc., 59 Temple
21  Place - Suite 330, Boston, MA  02111-1307, USA.
22
23  Further information about the GNU Lesser General Public License can also be found on
24  the world wide web at http://www.gnu.org.
25
26 HISTORY
27 --------------------------------------------------------------------------------
28 JSB  1/9/00          Created
29
30 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
31 SENTRY
32 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
33
34 #ifndef FGTABLE_H
35 #define FGTABLE_H
36
37 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
38 INCLUDES
39 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
40
41 #include "FGParameter.h"
42 #include <iosfwd>
43 #include <vector>
44 #include <string>
45
46 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
47 DEFINITIONS
48 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
49
50 #define ID_TABLE "$Id$"
51
52 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
53 FORWARD DECLARATIONS
54 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
55
56 namespace JSBSim {
57
58 class FGPropertyManager;
59 class Element;
60
61 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
62 CLASS DOCUMENTATION
63 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
64
65 /** Lookup table class.
66 Models a one, two, or three dimensional lookup table for use in aerodynamics
67 and function definitions.
68
69 For a single "vector" lookup table, the format is as follows:
70
71 @code
72 <table name="property_name">
73   <independentVar lookup="row"> property_name </independentVar>
74   <tableData>
75     key_1 value_1
76     key_2 value_2
77     ...  ...
78     key_n value_n
79   </tableData>
80 </table>
81 @endcode
82
83 The lookup="row" attribute in the independentVar element is option in this case;
84 it is assumed that the independentVar is a row variable.
85
86 A "real life" example is as shown here:
87
88 @code
89 <table>
90   <independentVar lookup="row"> aero/alpha-rad </independentVar>
91   <tableData>
92    -1.57  1.500
93    -0.26  0.033
94     0.00  0.025
95     0.26  0.033
96     1.57  1.500
97   </tableData>
98 </table>
99 @endcode
100
101 The first column in the data table represents the lookup index (or "key").  In
102 this case, the lookup index is aero/alpha-rad (angle of attack in radians).
103 If alpha is 0.26 radians, the value returned from the lookup table
104 would be 0.033.
105
106 The definition for a 2D table, is as follows:
107
108 @code
109 <table name="property_name">
110   <independentVar lookup="row"> property_name </independentVar>
111   <independentVar lookup="column"> property_name </independentVar>
112   <tableData>
113                 {col_1_key   col_2_key   ...  col_n_key }
114     {row_1_key} {col_1_data  col_2_data  ...  col_n_data}
115     {row_2_key} {...         ...         ...  ...       }
116     { ...     } {...         ...         ...  ...       }
117     {row_n_key} {...         ...         ...  ...       }
118   </tableData>
119 </table>
120 @endcode
121
122 The data is in a gridded format.
123
124 A "real life" example is as shown below. Alpha in radians is the row lookup (alpha
125 breakpoints are arranged in the first column) and flap position in degrees is
126
127 @code
128 <table>
129   <independentVar lookup="row">aero/alpha-rad</independentVar>
130   <independentVar lookup="column">fcs/flap-pos-deg</independentVar>
131   <tableData>
132                 0.0         10.0        20.0         30.0
133     -0.0523599  8.96747e-05 0.00231942  0.0059252    0.00835082
134     -0.0349066  0.000313268 0.00567451  0.0108461    0.0140545
135     -0.0174533  0.00201318  0.0105059   0.0172432    0.0212346
136      0.0        0.0051894   0.0168137   0.0251167    0.0298909
137      0.0174533  0.00993967  0.0247521   0.0346492    0.0402205
138      0.0349066  0.0162201   0.0342207   0.0457119    0.0520802
139      0.0523599  0.0240308   0.0452195   0.0583047    0.0654701
140      0.0698132  0.0333717   0.0577485   0.0724278    0.0803902
141      0.0872664  0.0442427   0.0718077   0.088081     0.0968405
142   </tableData>
143 </table>
144 @endcode
145
146 The definition for a 3D table in a coefficient would be (for example):
147
148 @code
149 <table name="property_name">
150   <independentVar lookup="row"> property_name </independentVar>
151   <independentVar lookup="column"> property_name </independentVar>
152   <tableData breakpoint="table_1_key">
153                 {col_1_key   col_2_key   ...  col_n_key }
154     {row_1_key} {col_1_data  col_2_data  ...  col_n_data}
155     {row_2_key} {...         ...         ...  ...       }
156     { ...     } {...         ...         ...  ...       }
157     {row_n_key} {...         ...         ...  ...       }
158   </tableData>
159   <tableData breakpoint="table_2_key">
160                 {col_1_key   col_2_key   ...  col_n_key }
161     {row_1_key} {col_1_data  col_2_data  ...  col_n_data}
162     {row_2_key} {...         ...         ...  ...       }
163     { ...     } {...         ...         ...  ...       }
164     {row_n_key} {...         ...         ...  ...       }
165   </tableData>
166   ...
167   <tableData breakpoint="table_n_key">
168                 {col_1_key   col_2_key   ...  col_n_key }
169     {row_1_key} {col_1_data  col_2_data  ...  col_n_data}
170     {row_2_key} {...         ...         ...  ...       }
171     { ...     } {...         ...         ...  ...       }
172     {row_n_key} {...         ...         ...  ...       }
173   </tableData>
174 </table>
175 @endcode
176
177 [Note the "breakpoint" attribute in the tableData element, above.]
178
179 Here's an example:
180
181 @code
182 <table>
183   <independentVar lookup="row">fcs/row-value</independentVar>
184   <independentVar lookup="column">fcs/column-value</independentVar>
185   <independentVar lookup="table">fcs/table-value</independentVar>
186   <tableData breakPoint="-1.0">
187            -1.0     1.0
188     0.0     1.0000  2.0000
189     1.0     3.0000  4.0000
190   </tableData>
191   <tableData breakPoint="0.0000">
192             0.0     10.0
193     2.0     1.0000  2.0000
194     3.0     3.0000  4.0000
195   </tableData>
196   <tableData breakPoint="1.0">
197            0.0     10.0     20.0
198      2.0   1.0000   2.0000   3.0000
199      3.0   4.0000   5.0000   6.0000
200     10.0   7.0000   8.0000   9.0000
201   </tableData>
202 </table>
203 @endcode
204
205 In addition to using a Table for something like a coefficient, where all the
206 row and column elements are read in from a file, a Table could be created
207 and populated completely within program code:
208
209 @code
210 // First column is thi, second is neta (combustion efficiency)
211 Lookup_Combustion_Efficiency = new FGTable(12);
212
213 *Lookup_Combustion_Efficiency << 0.00 << 0.980;
214 *Lookup_Combustion_Efficiency << 0.90 << 0.980;
215 *Lookup_Combustion_Efficiency << 1.00 << 0.970;
216 *Lookup_Combustion_Efficiency << 1.05 << 0.950;
217 *Lookup_Combustion_Efficiency << 1.10 << 0.900;
218 *Lookup_Combustion_Efficiency << 1.15 << 0.850;
219 *Lookup_Combustion_Efficiency << 1.20 << 0.790;
220 *Lookup_Combustion_Efficiency << 1.30 << 0.700;
221 *Lookup_Combustion_Efficiency << 1.40 << 0.630;
222 *Lookup_Combustion_Efficiency << 1.50 << 0.570;
223 *Lookup_Combustion_Efficiency << 1.60 << 0.525;
224 *Lookup_Combustion_Efficiency << 2.00 << 0.345;
225 @endcode
226
227 The first column in the table, above, is thi (the lookup index, or key). The
228 second column is the output data - in this case, "neta" (the Greek letter
229 referring to combustion efficiency). Later on, the table is used like this:
230
231 @code
232 combustion_efficiency = Lookup_Combustion_Efficiency->GetValue(equivalence_ratio);
233 @endcode
234
235 @author Jon S. Berndt
236 @version $Id$
237 */
238
239 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
240 CLASS DECLARATION
241 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
242
243 class FGTable : public FGParameter
244 {
245 public:
246   /// Destructor
247   ~FGTable();
248
249   /** This is the very important copy constructor.
250       @param table a const reference to a table.*/
251   FGTable(const FGTable& table);
252
253   /// The constructor for a table
254   FGTable (FGPropertyManager* propMan, Element* el);
255   FGTable (int );
256   double GetValue(void) const;
257   double GetValue(double key) const;
258   double GetValue(double rowKey, double colKey) const;
259   double GetValue(double rowKey, double colKey, double TableKey) const;
260   /** Read the table in.
261       Data in the config file should be in matrix format with the row
262       independents as the first column and the column independents in
263       the first row.  The implication of this layout is that there should
264       be no value in the upper left corner of the matrix e.g:
265       <pre>
266            0  10  20 30 ...
267       -5   1  2   3  4  ...
268        ...
269        </pre>
270
271        For multiple-table (i.e. 3D) data sets there is an additional number
272        key in the table definition. For example:
273
274       <pre>
275        0.0
276            0  10  20 30 ...
277       -5   1  2   3  4  ...
278        ...
279        </pre>
280        */
281
282   void operator<<(std::istream&);
283   FGTable& operator<<(const double n);
284   FGTable& operator<<(const int n);
285
286   inline double GetElement(int r, int c) {return Data[r][c];}
287   inline double GetElement(int r, int c, int t);
288
289   void SetRowIndexProperty(FGPropertyManager *node) {lookupProperty[eRow] = node;}
290   void SetColumnIndexProperty(FGPropertyManager *node) {lookupProperty[eColumn] = node;}
291
292   void Print(void);
293
294 private:
295   enum type {tt1D, tt2D, tt3D} Type;
296   enum axis {eRow=0, eColumn, eTable};
297   bool internal;
298   FGPropertyManager *lookupProperty[3];
299   double** Data;
300   std::vector <FGTable*> Tables;
301   unsigned int nRows, nCols, nTables, dimension;
302   int colCounter, rowCounter, tableCounter;
303   mutable int lastRowIndex, lastColumnIndex, lastTableIndex;
304   double** Allocate(void);
305   FGPropertyManager* const PropertyManager;
306   std::string Name;
307   void bind(void);
308
309   unsigned int FindNumColumns(const std::string&);
310   void Debug(int from);
311 };
312 }
313 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
314
315 #endif
316