]> git.mxchange.org Git - flightgear.git/blob - src/FDM/JSBSim/FGCoefficient.cpp
Fix stall widths for the "auxilliary" (reverse flow) stalls so they
[flightgear.git] / src / FDM / JSBSim / FGCoefficient.cpp
1 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2
3  Module:       FGCoefficient.cpp
4  Author:       Jon S. Berndt
5  Date started: 12/28/98
6  Purpose:      Encapsulates the stability derivative class FGCoefficient;
7  Called by:    FGAircraft
8
9  ------------- Copyright (C) 1999  Jon S. Berndt (jsb@hal-pc.org) -------------
10
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
14  version.
15
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
19  details.
20
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.
24
25  Further information about the GNU General Public License can also be found on
26  the world wide web at http://www.gnu.org.
27
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.
32
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.
36
37 See the header file FGCoefficient.h for the values of the identifiers.
38
39 HISTORY
40 --------------------------------------------------------------------------------
41 12/28/98   JSB   Created
42
43 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
44 INCLUDES
45 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
46
47 #include <stdio.h>
48
49 #include "FGCoefficient.h"
50 #include "FGState.h"
51 #include "FGFDMExec.h"
52 #include "FGPropertyManager.h"
53
54 #ifndef FGFS
55 #  if defined(sgi) && !defined(__GNUC__) && (_COMPILER_VERSION < 740)
56 #    include <iomanip.h>
57 #  else
58 #    include <iomanip>
59 #  endif
60 #else
61 #  include STL_IOMANIP
62 #endif
63
64 namespace JSBSim {
65
66 static const char *IdSrc = "$Id$";
67 static const char *IdHdr = ID_COEFFICIENT;
68
69 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
70 CLASS IMPLEMENTATION
71 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
72
73 FGCoefficient::FGCoefficient( FGFDMExec* fdex )
74 {
75   FDMExec = fdex;
76   State   = FDMExec->GetState();
77   Table   = 0;
78   IsFactor = false;
79
80   PropertyManager = FDMExec->GetPropertyManager();
81
82   Table = (FGTable*)0L;
83   LookupR = LookupC = 0;
84   numInstances = 0;
85   rows = columns = tables = 0;
86
87   StaticValue  = 0.0;
88   totalValue   = 0.0;
89   bias = 0.0;
90   gain = 1.0;
91   SD = 0.0;
92
93   filename.erase();
94   description.erase();
95   name.erase();
96   method.erase();
97   multparms.erase();
98   multparmsRow.erase();
99   multparmsCol.erase();
100
101   Debug(0);
102 }
103
104 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
105
106 FGCoefficient::~FGCoefficient()
107 {
108   if (Table) delete Table;
109   Debug(1);
110 }
111
112 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
113
114 bool FGCoefficient::Load(FGConfigFile *AC_cfg)
115 {
116   int start, end, n;
117   string mult;
118
119   if (AC_cfg) {
120     name = AC_cfg->GetValue("NAME");
121     method = AC_cfg->GetValue("TYPE");
122     AC_cfg->GetNextConfigLine();
123     *AC_cfg >> description;
124     if      (method == "EQUATION") type = EQUATION;
125     else if (method == "TABLE")    type = TABLE;
126     else if (method == "TABLE3D")  type = TABLE3D;
127     else if (method == "VECTOR")   type = VECTOR;
128     else if (method == "VALUE")    type = VALUE;
129     else                           type = UNKNOWN;
130
131     if (type == VECTOR || type == TABLE || type == TABLE3D) {
132
133       if (type == TABLE3D) {
134         *AC_cfg >> rows >> columns >> tables;
135         Table = new FGTable(rows, columns, tables);
136         *AC_cfg >> multparmsRow >> multparmsCol >> multparmsTable;
137         LookupR = PropertyManager->GetNode( multparmsRow );
138         LookupC = PropertyManager->GetNode( multparmsCol );
139         LookupT = PropertyManager->GetNode( multparmsTable );
140       } else if (type == TABLE) {
141         *AC_cfg >> rows >> columns;
142         Table = new FGTable(rows, columns);
143         *AC_cfg >> multparmsRow >> multparmsCol;
144         LookupR = PropertyManager->GetNode( multparmsRow );
145         LookupC = PropertyManager->GetNode( multparmsCol );
146       } else {
147         *AC_cfg >> rows;
148         Table = new FGTable(rows);
149         *AC_cfg >> multparmsRow;
150         LookupR = PropertyManager->GetNode( multparmsRow );
151       }
152     }
153
154     // Here, read in the line of the form:
155     // {property1} | {property2} | {property3}
156     // where each non-dimensionalizing property for this coefficient is
157     // separated by a | character
158
159     string line=AC_cfg->GetCurrentLine();
160     unsigned j=0;
161     char tmp[255];
162     for(unsigned i=0;i<line.length(); i++ ) {
163       if( !isspace(line[i]) ) {
164         tmp[j]=line[i];
165         j++;
166       }
167     }
168     tmp[j]='\0'; multparms=tmp;
169     end = multparms.length();
170
171     n = multparms.find("|");
172     if (n == string::npos) n = end;
173     start = 0;
174     if (multparms != string("none")) {
175       while (n < end && n != string::npos) {
176         n -= start;
177         mult = multparms.substr(start,n);
178         multipliers.push_back( resolveSymbol( mult ) );
179         start += n+1;
180         n = multparms.find("|",start);
181       }
182       mult = multparms.substr(start,n);
183       multipliers.push_back( resolveSymbol( mult ) );
184       // End of non-dimensionalizing parameter read-in
185     }
186     AC_cfg->GetNextConfigLine();
187
188     if (type == VALUE) {
189       *AC_cfg >> StaticValue;
190     } else if (type == VECTOR || type == TABLE || type == TABLE3D) {
191       *Table << *AC_cfg;
192     } else {
193       cerr << "Unimplemented coefficient type: " << type << endl;
194     }
195
196     AC_cfg->GetNextConfigLine();
197     FGCoefficient::Debug(2);
198
199     return true;
200   } else {
201     return false;
202   }
203 }
204
205
206
207 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
208
209 double FGCoefficient::Value(double rVal, double cVal, double tVal)
210 {
211   double Value;
212   unsigned int midx;
213
214   SD = Value = gain*Table->GetValue(rVal, cVal, tVal) + bias;
215
216   for (midx=0; midx < multipliers.size(); midx++) {
217       Value *= multipliers[midx]->getDoubleValue();
218   }
219   return Value;
220 }
221
222 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
223
224 double FGCoefficient::Value(double rVal, double cVal)
225 {
226   double Value;
227   unsigned int midx;
228
229   SD = Value = gain*Table->GetValue(rVal, cVal) + bias;
230
231   for (midx=0; midx < multipliers.size(); midx++) {
232       Value *= multipliers[midx]->getDoubleValue();
233   }
234   return Value;
235 }
236
237 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
238
239 double FGCoefficient::Value(double Val)
240 {
241   double Value;
242
243   SD = Value = gain*Table->GetValue(Val) + bias;
244
245   for (unsigned int midx=0; midx < multipliers.size(); midx++)
246       Value *= multipliers[midx]->getDoubleValue();
247
248   return Value;
249 }
250
251 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
252
253 double FGCoefficient::Value(void)
254 {
255   double Value;
256
257   SD = Value = gain*StaticValue + bias;
258
259   for (unsigned int midx=0; midx < multipliers.size(); midx++)
260     Value *= multipliers[midx]->getDoubleValue();
261
262   return Value;
263 }
264
265 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
266
267 double FGCoefficient::TotalValue(void)
268 {
269   switch(type) {
270
271   case UNKNOWN:
272     totalValue = -1;
273     break;
274
275   case VALUE:
276     totalValue = Value();
277     break;
278
279   case VECTOR:
280     totalValue = Value( LookupR->getDoubleValue() );
281     break;
282
283   case TABLE:
284     totalValue = Value( LookupR->getDoubleValue(),
285                         LookupC->getDoubleValue() );
286     break;
287
288   case TABLE3D:
289     totalValue = Value( LookupR->getDoubleValue(),
290                         LookupC->getDoubleValue(),
291                         LookupT->getDoubleValue() );
292     break;
293
294   case EQUATION:
295     totalValue = 0.0;
296     break;
297   }
298   return totalValue;
299 }
300
301 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
302
303 void FGCoefficient::DisplayCoeffFactors(void)
304 {
305   unsigned int i;
306
307   cout << "   Non-Dimensionalized by: ";
308
309   if (multipliers.size() == 0) {
310     cout << "none" << endl;
311   } else {
312     for (i=0; i<multipliers.size(); i++)
313       cout << multipliers[i]->getName() << "  ";
314   }
315   cout << endl;
316 }
317
318 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
319
320 string FGCoefficient::GetSDstring(void)
321 {
322   char buffer[20];
323   string value;
324
325   sprintf(buffer,"%9.6f",SD);
326   value = string(buffer);
327   return value;
328 }
329
330 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
331
332 void FGCoefficient::bind(FGPropertyManager *parent)
333 {
334   string mult;
335   unsigned i;
336
337   node = parent->GetNode(name,true);
338
339   node->SetString("description",description);
340   if (LookupR) node->SetString("row-parm",LookupR->getName() );
341   if (LookupC) node->SetString("column-parm",LookupC->getName() );
342
343   mult="";
344   if (multipliers.size() == 0)
345     mult="none";
346
347   for (i=0; i<multipliers.size(); i++) {
348       mult += multipliers[i]->getName();
349       if ( i < multipliers.size()-1 ) mult += " ";
350   }
351   node->SetString("multipliers",mult);
352
353   node->Tie("SD-norm",this,&FGCoefficient::GetSD );
354   node->Tie("value-lbs",this,&FGCoefficient::GetValue );
355
356   node->Tie("bias", this, &FGCoefficient::getBias,
357                           &FGCoefficient::setBias );
358
359   node->Tie("gain", this, &FGCoefficient::getGain,
360                           &FGCoefficient::setGain );
361
362 }
363
364 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
365
366 void FGCoefficient::unbind(void)
367 {
368   node->Untie("SD-norm");
369   node->Untie("value-lbs");
370   node->Untie("bias");
371   node->Untie("gain");
372 }
373
374 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
375
376 FGPropertyManager* FGCoefficient::resolveSymbol(string name)
377 {
378   FGPropertyManager* tmpn;
379
380   tmpn = PropertyManager->GetNode(name,false);
381   if ( !tmpn ) {
382     cerr << "Coefficient multipliers cannot create properties, check spelling?" << endl;
383     exit(1);
384   }
385   return tmpn;
386 }
387
388 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
389
390 void FGCoefficient::convert(string prop)
391 {
392   if (IsFactor)
393     cout << "            <function name=\"aero/function/" << name << "\">" << endl;
394   else
395     cout << "            <function name=\"aero/coefficient/" << name << "\">" << endl;
396
397   cout << "                <description>" << description << "</description>" << endl;
398   cout << "                <product>" << endl;
399
400   for (int i=0; i<multipliers.size(); i++)
401     cout << "                    <property>" << (multipliers[i]->GetFullyQualifiedName()).substr(12) << "</property>" << endl;
402
403   if (!prop.empty())
404     cout << "                    <property>aero/function/" << prop << "</property>" << endl;
405
406   switch (type) {
407   case VALUE:
408   cout << "                    <value>" << StaticValue << "</value>" << endl;
409     break;
410
411   case VECTOR:
412     cout << "                      <table>" << endl;
413     cout << "                          <independentVar>" << (LookupR->GetFullyQualifiedName()).substr(12) << "</independentVar>" << endl;
414     cout << "                          <tableData>" << endl;
415     Table->Print(30);
416     cout << "                          </tableData>" << endl;
417     cout << "                      </table>" << endl;
418     break;
419
420   case TABLE:
421     cout << "                      <table>" << endl;
422     cout << "                          <independentVar lookup=\"row\">" << (LookupR->GetFullyQualifiedName()).substr(12) << "</independentVar>" << endl;
423     cout << "                          <independentVar lookup=\"column\">" << (LookupC->GetFullyQualifiedName()).substr(12) << "</independentVar>" << endl;
424     cout << "                          <tableData>" << endl;
425     Table->Print(30);
426     cout << "                          </tableData>" << endl;
427     cout << "                      </table>" << endl;
428     break;
429
430   case TABLE3D:
431     cout << "                      <table>" << endl;
432     cout << "                          <independentVar lookup=\"row\">" << (LookupR->GetFullyQualifiedName()).substr(12) << "</independentVar>" << endl;
433     cout << "                          <independentVar lookup=\"column\">" << (LookupC->GetFullyQualifiedName()).substr(12) << "</independentVar>" << endl;
434     cout << "                          <independentVar lookup=\"table\">" << (LookupT->GetFullyQualifiedName()).substr(12) << "</independentVar>" << endl;
435     cout << "                          <tableData>" << endl;
436     Table->Print(30);
437     cout << "                          </tableData>" << endl;
438     cout << "                      </table>" << endl;
439     break;
440
441   }
442
443   cout << "                </product>" << endl;
444   cout << "            </function>" << endl;
445
446   if (IsFactor) {
447   cout << " === MOVE THE ABOVE FACTOR " << name << " OUTSIDE OF AND BEFORE ANY <AXIS> DEFINITION ===" << endl;
448     for (int i=0; i<sum.size(); i++) {
449       sum[i]->convert(name);
450     }
451   }
452 }
453
454 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
455 //    The bitmasked value choices are as follows:
456 //    unset: In this case (the default) JSBSim would only print
457 //       out the normally expected messages, essentially echoing
458 //       the config files as they are read. If the environment
459 //       variable is not set, debug_lvl is set to 1 internally
460 //    0: This requests JSBSim not to output any messages
461 //       whatsoever.
462 //    1: This value explicity requests the normal JSBSim
463 //       startup messages
464 //    2: This value asks for a message to be printed out when
465 //       a class is instantiated
466 //    4: When this value is set, a message is displayed when a
467 //       FGModel object executes its Run() method
468 //    8: When this value is set, various runtime state variables
469 //       are printed out periodically
470 //    16: When set various parameters are sanity checked and
471 //       a message is printed out when they go out of bounds
472
473 void FGCoefficient::Debug(int from)
474 {
475   if (debug_lvl <= 0) return;
476
477   if (debug_lvl & 1) { // Standard console startup message output
478
479     if (from == 2) { // Loading
480       cout << "\n   " << highint << underon << name << underoff << normint << endl;
481       cout << "   " << description << endl;
482       cout << "   " << method << endl;
483
484       if (type == VECTOR || type == TABLE || type == TABLE3D) {
485         cout << "   Rows: " << rows << " indexed by: " << LookupR->getName() << endl;
486         if (type == TABLE || type == TABLE3D) {
487           cout << "   Cols: " << columns << " indexed by: " << LookupC->getName() << endl;
488           if (type == TABLE3D) {
489             cout << "   Tables: " << tables << " indexed by: " << LookupT->getName() << endl;
490           }
491         }
492         Table->Print();
493       } else if (type == VALUE) {
494         cout << "      Value = " << StaticValue << endl;
495       }
496
497       DisplayCoeffFactors();
498     }
499   }
500   if (debug_lvl & 2 ) { // Instantiation/Destruction notification
501     if (from == 0) cout << "Instantiated: FGCoefficient" << endl;
502     if (from == 1) cout << "Destroyed:    FGCoefficient" << endl;
503   }
504   if (debug_lvl & 4 ) { // Run() method entry print for FGModel-derived objects
505   }
506   if (debug_lvl & 8 ) { // Runtime state variables
507   }
508   if (debug_lvl & 16) { // Sanity checking
509   }
510   if (debug_lvl & 64) {
511     if (from == 0) { // Constructor
512       cout << IdSrc << endl;
513       cout << IdHdr << endl;
514     }
515   }
516 }
517
518 } // namespace JSBSim