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 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
49 #include "FGCoefficient.h"
51 #include "FGFDMExec.h"
52 #include "FGPropertyManager.h"
55 # if defined(sgi) && !defined(__GNUC__) && (_COMPILER_VERSION < 740)
66 static const char *IdSrc = "$Id$";
67 static const char *IdHdr = ID_COEFFICIENT;
69 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
71 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
73 FGCoefficient::FGCoefficient( FGFDMExec* fdex )
76 State = FDMExec->GetState();
80 PropertyManager = FDMExec->GetPropertyManager();
83 LookupR = LookupC = 0;
85 rows = columns = tables = 0;
104 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
106 FGCoefficient::~FGCoefficient()
108 if (Table) delete Table;
112 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
114 bool FGCoefficient::Load(FGConfigFile *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;
131 if (type == VECTOR || type == TABLE || type == TABLE3D) {
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 );
148 Table = new FGTable(rows);
149 *AC_cfg >> multparmsRow;
150 LookupR = PropertyManager->GetNode( multparmsRow );
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
159 string line=AC_cfg->GetCurrentLine();
162 for(unsigned i=0;i<line.length(); i++ ) {
163 if( !isspace(line[i]) ) {
168 tmp[j]='\0'; multparms=tmp;
169 end = multparms.length();
171 n = multparms.find("|");
172 if (n == string::npos) n = end;
174 if (multparms != string("none")) {
175 while (n < end && n != string::npos) {
177 mult = multparms.substr(start,n);
178 multipliers.push_back( resolveSymbol( mult ) );
180 n = multparms.find("|",start);
182 mult = multparms.substr(start,n);
183 multipliers.push_back( resolveSymbol( mult ) );
184 // End of non-dimensionalizing parameter read-in
186 AC_cfg->GetNextConfigLine();
189 *AC_cfg >> StaticValue;
190 } else if (type == VECTOR || type == TABLE || type == TABLE3D) {
193 cerr << "Unimplemented coefficient type: " << type << endl;
196 AC_cfg->GetNextConfigLine();
197 FGCoefficient::Debug(2);
207 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
209 double FGCoefficient::Value(double rVal, double cVal, double tVal)
214 SD = Value = gain*Table->GetValue(rVal, cVal, tVal) + bias;
216 for (midx=0; midx < multipliers.size(); midx++) {
217 Value *= multipliers[midx]->getDoubleValue();
222 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
224 double FGCoefficient::Value(double rVal, double cVal)
229 SD = Value = gain*Table->GetValue(rVal, cVal) + bias;
231 for (midx=0; midx < multipliers.size(); midx++) {
232 Value *= multipliers[midx]->getDoubleValue();
237 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
239 double FGCoefficient::Value(double Val)
243 SD = Value = gain*Table->GetValue(Val) + bias;
245 for (unsigned int midx=0; midx < multipliers.size(); midx++)
246 Value *= multipliers[midx]->getDoubleValue();
251 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
253 double FGCoefficient::Value(void)
257 SD = Value = gain*StaticValue + bias;
259 for (unsigned int midx=0; midx < multipliers.size(); midx++)
260 Value *= multipliers[midx]->getDoubleValue();
265 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
267 double FGCoefficient::TotalValue(void)
276 totalValue = Value();
280 totalValue = Value( LookupR->getDoubleValue() );
284 totalValue = Value( LookupR->getDoubleValue(),
285 LookupC->getDoubleValue() );
289 totalValue = Value( LookupR->getDoubleValue(),
290 LookupC->getDoubleValue(),
291 LookupT->getDoubleValue() );
301 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
303 void FGCoefficient::DisplayCoeffFactors(void)
307 cout << " Non-Dimensionalized by: ";
309 if (multipliers.size() == 0) {
310 cout << "none" << endl;
312 for (i=0; i<multipliers.size(); i++)
313 cout << multipliers[i]->getName() << " ";
318 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
320 string FGCoefficient::GetSDstring(void)
325 sprintf(buffer,"%9.6f",SD);
326 value = string(buffer);
330 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
332 void FGCoefficient::bind(FGPropertyManager *parent)
337 node = parent->GetNode(name,true);
339 node->SetString("description",description);
340 if (LookupR) node->SetString("row-parm",LookupR->getName() );
341 if (LookupC) node->SetString("column-parm",LookupC->getName() );
344 if (multipliers.size() == 0)
347 for (i=0; i<multipliers.size(); i++) {
348 mult += multipliers[i]->getName();
349 if ( i < multipliers.size()-1 ) mult += " ";
351 node->SetString("multipliers",mult);
353 node->Tie("SD-norm",this,&FGCoefficient::GetSD );
354 node->Tie("value-lbs",this,&FGCoefficient::GetValue );
356 node->Tie("bias", this, &FGCoefficient::getBias,
357 &FGCoefficient::setBias );
359 node->Tie("gain", this, &FGCoefficient::getGain,
360 &FGCoefficient::setGain );
364 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
366 void FGCoefficient::unbind(void)
368 node->Untie("SD-norm");
369 node->Untie("value-lbs");
374 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
376 FGPropertyManager* FGCoefficient::resolveSymbol(string name)
378 FGPropertyManager* tmpn;
380 tmpn = PropertyManager->GetNode(name,false);
382 cerr << "Coefficient multipliers cannot create properties, check spelling?" << endl;
388 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
390 void FGCoefficient::convert(string prop)
393 cout << " <function name=\"aero/function/" << name << "\">" << endl;
395 cout << " <function name=\"aero/coefficient/" << name << "\">" << endl;
397 cout << " <description>" << description << "</description>" << endl;
398 cout << " <product>" << endl;
400 for (int i=0; i<multipliers.size(); i++)
401 cout << " <property>" << (multipliers[i]->GetFullyQualifiedName()).substr(12) << "</property>" << endl;
404 cout << " <property>aero/function/" << prop << "</property>" << endl;
408 cout << " <value>" << StaticValue << "</value>" << endl;
412 cout << " <table>" << endl;
413 cout << " <independentVar>" << (LookupR->GetFullyQualifiedName()).substr(12) << "</independentVar>" << endl;
414 cout << " <tableData>" << endl;
416 cout << " </tableData>" << endl;
417 cout << " </table>" << endl;
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;
426 cout << " </tableData>" << endl;
427 cout << " </table>" << endl;
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;
437 cout << " </tableData>" << endl;
438 cout << " </table>" << endl;
443 cout << " </product>" << endl;
444 cout << " </function>" << endl;
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);
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
462 // 1: This value explicity requests the normal JSBSim
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
473 void FGCoefficient::Debug(int from)
475 if (debug_lvl <= 0) return;
477 if (debug_lvl & 1) { // Standard console startup message output
479 if (from == 2) { // Loading
480 cout << "\n " << highint << underon << name << underoff << normint << endl;
481 cout << " " << description << endl;
482 cout << " " << method << endl;
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;
493 } else if (type == VALUE) {
494 cout << " Value = " << StaticValue << endl;
497 DisplayCoeffFactors();
500 if (debug_lvl & 2 ) { // Instantiation/Destruction notification
501 if (from == 0) cout << "Instantiated: FGCoefficient" << endl;
502 if (from == 1) cout << "Destroyed: FGCoefficient" << endl;
504 if (debug_lvl & 4 ) { // Run() method entry print for FGModel-derived objects
506 if (debug_lvl & 8 ) { // Runtime state variables
508 if (debug_lvl & 16) { // Sanity checking
510 if (debug_lvl & 64) {
511 if (from == 0) { // Constructor
512 cout << IdSrc << endl;
513 cout << IdHdr << endl;
518 } // namespace JSBSim