1 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3 Module: FGCoefficient.cpp
6 Purpose: Encapsulates the stability derivative class FGCoefficient;
9 ------------- Copyright (C) 1999 Jon S. Berndt (jsb@hal-pc.org) -------------
11 This program is free software; you can redistribute it and/or modify it under
12 the terms of the GNU General Public License as published by the Free Software
13 Foundation; either version 2 of the License, or (at your option) any later
16 This program is distributed in the hope that it will be useful, but WITHOUT
17 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
18 FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
21 You should have received a copy of the GNU General Public License along with
22 this program; if not, write to the Free Software Foundation, Inc., 59 Temple
23 Place - Suite 330, Boston, MA 02111-1307, USA.
25 Further information about the GNU General Public License can also be found on
26 the world wide web at http://www.gnu.org.
28 FUNCTIONAL DESCRIPTION
29 --------------------------------------------------------------------------------
30 This class models the stability derivative coefficient lookup tables or
31 equations. Note that the coefficients need not be calculated each delta-t.
33 Note that the values in a row which index into the table must be the same value
34 for each column of data, so the first column of numbers for each altitude are
35 seen to be equal, and there are the same number of values for each altitude.
37 See the header file FGCoefficient.h for the values of the identifiers.
40 --------------------------------------------------------------------------------
43 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
45 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
47 #include "FGCoefficient.h"
49 #include "FGFDMExec.h"
53 static const char *IdSrc = "$Header$";
54 static const char *IdHdr = "ID_COEFFICIENT";
56 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
58 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
60 FGCoefficient::FGCoefficient(FGFDMExec* fdex, FGConfigFile* AC_cfg)
62 int r, c, start, end, n;
65 char nullstring[13] = " ";
71 State = FDMExec->GetState();
75 name = AC_cfg->GetValue("NAME");
76 method = AC_cfg->GetValue("TYPE");
78 AC_cfg->GetNextConfigLine();
79 *AC_cfg >> description;
96 cout << " " << bolden << name << unbolden << endl;
97 cout << " " << description << endl;
98 cout << " " << method << endl;
100 if (method == "EQUATION") type = EQUATION;
101 else if (method == "TABLE") type = TABLE;
102 else if (method == "VECTOR") type = VECTOR;
103 else if (method == "VALUE") type = VALUE;
106 if (type == VECTOR || type == TABLE) {
108 cout << " Rows: " << rows << " ";
111 cout << "Cols: " << columns;
116 *AC_cfg >> multparms;
117 LookupR = State->GetParameterIndex(multparms);
118 cout << " Row indexing parameter: " << multparms << endl;
122 *AC_cfg >> multparms;
123 LookupC = State->GetParameterIndex(multparms);
124 cout << " Column indexing parameter: " << multparms << endl;
127 // Here, read in the line of the form (e.g.) FG_MACH|FG_QBAR|FG_ALPHA
128 // where each non-dimensionalizing parameter for this coefficient is
129 // separated by a | character
131 *AC_cfg >> multparms;
133 end = multparms.length();
134 n = multparms.find("|");
137 while (n < end && n >= 0) {
139 multipliers.push_back(State->GetParameterIndex(multparms.substr(start,n)));
141 n = multparms.find("|",start);
144 multipliers.push_back(State->GetParameterIndex(multparms.substr(start,n)));
146 // End of non-dimensionalizing parameter read-in
150 *AC_cfg >> StaticValue;
151 cout << " Value = " << StaticValue << endl;
156 for (r=1;r<=rows;r++) {
157 *AC_cfg >> Table[r][0];
158 *AC_cfg >> Table[r][1];
161 for (r=1;r<=rows;r++) {
163 for (c=0;c<columns;c++) {
164 cout << Table[r][c] << " ";
171 Allocate(rows, columns);
175 // Read the table in -- it should be in matrix format with the row
176 // independents as the first column and the column independents in
177 // the first row. The implication of this layout is that there should
178 // be no value in the upper left corner of the matrix e.g:
183 for (r=0; r<=rows; r++) {
184 for (c=0; c <= columns; c++) {
185 if ( !((r == 0) && (c == 0)) ) {
186 *AC_cfg >> Table[r][c];
191 /* for (c=1;c<=columns;c++) {
192 *AC_cfg >> Table[0][c];
193 for (r=1;r<=rows;r++) {
194 if ( c==1 ) *AC_cfg >> Table[r][0];
195 else *AC_cfg >> ftrashcan;
196 *AC_cfg >> Table[r][c];
200 for (r=0;r<=rows;r++) {
202 for (c=0;c<=columns;c++) {
203 if( ((r == 0) && (c == 0)) ) {
206 cout.flags(ios::left);
207 cout << setw(12) << Table[r][c];
216 cerr << "Unimplemented coefficient type: " << type << endl;
219 AC_cfg->GetNextConfigLine();
223 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
225 FGCoefficient::~FGCoefficient(void) {
229 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
231 bool FGCoefficient::DeAllocate(void)
233 if (Table != NULL ) {
234 for (unsigned int i=0; i<=rows; i++) delete[] Table[i];
242 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
244 bool FGCoefficient::Allocate(int r, int c)
248 Table = new float*[r+1];
249 for (int i=0;i<=r;i++) Table[i] = new float[c+1];
253 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
255 float FGCoefficient::Value(float rVal, float cVal)
257 float rFactor, cFactor, col1temp, col2temp, Value;
261 if (rows < 2 || columns < 2) return 0.0;
263 for (r=1;r<=rows;r++) if (Table[r][0] >= rVal) break;
264 for (c=1;c<=columns;c++) if (Table[0][c] >= cVal) break;
265 //cout << "Value(): rVal: " << rVal << " cVal: " << cVal << endl;
266 //cout << "Value(): r: " << r << " c: " << c << endl;
267 c = c < 2 ? 2 : (c > columns ? columns : c);
268 r = r < 2 ? 2 : (r > rows ? rows : r);
270 rFactor = (rVal - Table[r-1][0]) / (Table[r][0] - Table[r-1][0]);
271 cFactor = (cVal - Table[0][c-1]) / (Table[0][c] - Table[0][c-1]);
273 col1temp = rFactor*(Table[r][c-1] - Table[r-1][c-1]) + Table[r-1][c-1];
274 col2temp = rFactor*(Table[r][c] - Table[r-1][c]) + Table[r-1][c];
276 Value = col1temp + cFactor*(col2temp - col1temp);
277 Value = (Value + bias)*gain;
280 for (midx=0; midx < multipliers.size(); midx++) {
281 Value *= State->GetParameter(multipliers[midx]);
287 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
289 float FGCoefficient::Value(float Val)
297 if (rows < 2) return 0.0;
299 for (r=1;r<=rows;r++) if (Table[r][0] >= Val) break;
300 r = r < 2 ? 2 : (r > rows ? rows : r);
302 // make sure denominator below does not go to zero.
303 if (Table[r][0] != Table[r-1][0]) {
304 Factor = (Val - Table[r-1][0]) / (Table[r][0] - Table[r-1][0]);
309 Value = Factor*(Table[r][1] - Table[r-1][1]) + Table[r-1][1];
310 Value = (Value + bias)*gain;
313 for (midx=0; midx < multipliers.size(); midx++) {
314 Value *= State->GetParameter(multipliers[midx]);
321 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
323 float FGCoefficient::Value(void)
329 Value = (Value + bias)*gain;
332 for (midx=0; midx < multipliers.size(); midx++) {
333 Value *= State->GetParameter(multipliers[midx]);
339 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
341 float FGCoefficient::TotalValue()
349 return (Value(State->GetParameter(LookupR)));
351 return (Value(State->GetParameter(LookupR),State->GetParameter(LookupC)));
358 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
360 void FGCoefficient::DumpSD(void)
362 cout << " " << name << ": " << SD << endl;
365 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%