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