1 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3 Module: FGBuoyantForces.cpp
4 Authors: Anders Gidenstam, Jon S. Berndt
6 Purpose: Encapsulates the buoyant forces
8 ------------- Copyright (C) 2008 - 2009 Anders Gidenstam -------------
9 ------------- Copyright (C) 2008 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 Lesser 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 Lesser General Public License for more
21 You should have received a copy of the GNU Lesser 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 Lesser General Public License can also be found on
26 the world wide web at http://www.gnu.org.
28 FUNCTIONAL DESCRIPTION
29 --------------------------------------------------------------------------------
32 --------------------------------------------------------------------------------
35 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
37 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
39 #include "FGBuoyantForces.h"
40 #include "FGMassBalance.h"
41 #include <input_output/FGPropertyManager.h> // Need?
45 static const char *IdSrc = "$Id$";
46 static const char *IdHdr = ID_BUOYANTFORCES;
48 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
50 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
52 FGBuoyantForces::FGBuoyantForces(FGFDMExec* FDMExec) : FGModel(FDMExec)
54 Name = "FGBuoyantForces";
58 vTotalForces.InitMatrix();
59 vTotalMoments.InitMatrix();
61 gasCellJ.InitMatrix();
68 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
70 FGBuoyantForces::~FGBuoyantForces()
72 for (unsigned int i=0; i<Cells.size(); i++) delete Cells[i];
75 for (unsigned int i=0; i<interface_properties.size(); i++)
76 delete interface_properties[i];
77 interface_properties.clear();
82 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
84 bool FGBuoyantForces::InitModel(void)
86 if (!FGModel::InitModel()) return false;
91 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
93 bool FGBuoyantForces::Run(void)
95 if (FGModel::Run()) return true;
96 if (FDMExec->Holding()) return false; // if paused don't execute
97 if (NoneDefined) return true;
99 vTotalForces.InitMatrix();
100 vTotalMoments.InitMatrix();
102 for (unsigned int i=0; i<Cells.size(); i++) {
103 Cells[i]->Calculate(FDMExec->GetDeltaT());
104 vTotalForces += Cells[i]->GetBodyForces();
105 vTotalMoments += Cells[i]->GetMoments();
111 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
113 bool FGBuoyantForces::Load(Element *element)
115 string fname="", file="";
116 Element *gas_cell_element;
120 string separator = "/";
122 fname = element->GetAttributeValue("file");
123 if (!fname.empty()) {
124 file = FDMExec->GetFullAircraftPath() + separator + fname;
125 document = LoadXMLDocument(file);
130 Element *property_element = document->FindElement("property");
131 if (property_element)
132 cout << endl << " Declared properties" << endl << endl;
133 while (property_element) {
134 string interface_property_string = property_element->GetDataLine();
136 if (PropertyManager->HasNode(interface_property_string)) {
137 cout << " Property " << interface_property_string <<
138 " is already defined." << endl;
141 if ( ! property_element->GetAttributeValue("value").empty())
142 value = property_element->GetAttributeValueAsNumber("value");
143 interface_properties.push_back(new double(value));
144 interface_property_string = property_element->GetDataLine();
145 PropertyManager->Tie(interface_property_string,
146 interface_properties.back());
147 cout << " " << interface_property_string <<
148 " (initial value: " << value << ")" << endl;
150 property_element = document->FindNextElement("property");
153 gas_cell_element = document->FindElement("gas_cell");
154 while (gas_cell_element) {
156 Cells.push_back(new FGGasCell(FDMExec, gas_cell_element, Cells.size()));
157 gas_cell_element = document->FindNextElement("gas_cell");
163 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
165 double FGBuoyantForces::GetGasMass(void)
169 for (unsigned int i = 0; i < Cells.size(); i++) {
170 Gw += Cells[i]->GetMass();
176 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
178 const FGColumnVector3& FGBuoyantForces::GetGasMassMoment(void)
180 vXYZgasCell_arm.InitMatrix();
181 for (unsigned int i = 0; i < Cells.size(); i++) {
182 vXYZgasCell_arm += Cells[i]->GetMassMoment();
184 return vXYZgasCell_arm;
187 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
189 const FGMatrix33& FGBuoyantForces::GetGasMassInertia(void)
191 const unsigned int size = Cells.size();
193 if (size == 0) return gasCellJ;
195 gasCellJ = FGMatrix33();
197 for (unsigned int i=0; i < size; i++) {
198 FGColumnVector3 v = MassBalance->StructuralToBody( Cells[i]->GetXYZ() );
199 // Body basis is in FT.
200 const double mass = Cells[i]->GetMass();
202 // FIXME: Verify that this is the correct way to change between the
203 // coordinate frames.
204 gasCellJ += Cells[i]->GetInertia() +
205 FGMatrix33( 0, - mass*v(1)*v(2), - mass*v(1)*v(3),
206 - mass*v(2)*v(1), 0, - mass*v(2)*v(3),
207 - mass*v(3)*v(1), - mass*v(3)*v(2), 0 );
213 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
215 string FGBuoyantForces::GetBuoyancyStrings(string delimeter)
217 string CoeffStrings = "";
219 bool firstime = true;
220 for (sd = 0; sd < variables.size(); sd++) {
224 CoeffStrings += delimeter;
226 CoeffStrings += variables[sd]->GetName();
229 for (axis = 0; axis < 6; axis++) {
230 for (sd = 0; sd < Coeff[axis].size(); sd++) {
234 CoeffStrings += delimeter;
236 CoeffStrings += Coeff[axis][sd]->GetName();
243 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
245 string FGBuoyantForces::GetBuoyancyValues(string delimeter)
247 string SDValues = "";
249 bool firstime = true;
250 for (sd = 0; sd < variables.size(); sd++) {
254 SDValues += delimeter;
256 SDValues += variables[sd]->GetValueAsString();
259 for (unsigned int axis = 0; axis < 6; axis++) {
260 for (unsigned int sd = 0; sd < Coeff[axis].size(); sd++) {
264 SDValues += delimeter;
266 SDValues += Coeff[axis][sd]->GetValueAsString();
273 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
275 void FGBuoyantForces::bind(void)
279 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
280 // The bitmasked value choices are as follows:
281 // unset: In this case (the default) JSBSim would only print
282 // out the normally expected messages, essentially echoing
283 // the config files as they are read. If the environment
284 // variable is not set, debug_lvl is set to 1 internally
285 // 0: This requests JSBSim not to output any messages
287 // 1: This value explicity requests the normal JSBSim
289 // 2: This value asks for a message to be printed out when
290 // a class is instantiated
291 // 4: When this value is set, a message is displayed when a
292 // FGModel object executes its Run() method
293 // 8: When this value is set, various runtime state variables
294 // are printed out periodically
295 // 16: When set various parameters are sanity checked and
296 // a message is printed out when they go out of bounds
298 void FGBuoyantForces::Debug(int from)
300 if (debug_lvl <= 0) return;
302 if (debug_lvl & 1) { // Standard console startup message output
303 if (from == 2) { // Loader
304 cout << endl << " Buoyant Forces: " << endl;
307 if (debug_lvl & 2 ) { // Instantiation/Destruction notification
308 if (from == 0) cout << "Instantiated: FGBuoyantForces" << endl;
309 if (from == 1) cout << "Destroyed: FGBuoyantForces" << endl;
311 if (debug_lvl & 4 ) { // Run() method entry print for FGModel-derived objects
313 if (debug_lvl & 8 ) { // Runtime state variables
315 if (debug_lvl & 16) { // Sanity checking
317 if (debug_lvl & 64) {
318 if (from == 0) { // Constructor
319 cout << IdSrc << endl;
320 cout << IdHdr << endl;
325 } // namespace JSBSim