Esempio n. 1
0
FGTank::FGTank(FGFDMExec* exec, Element* el, int tank_number)
                  : TankNumber(tank_number)
{
  string token, strFuelName;
  Element* element;
  Element* element_Grain;
  FGPropertyManager *PropertyManager = exec->GetPropertyManager();
  Area = 1.0;
  Density = 6.6;
  InitialTemperature = Temperature = -9999.0;
  Ixx = Iyy = Izz = 0.0;
  InertiaFactor = 1.0;
  Radius = Contents = Standpipe = Length = InnerRadius = 0.0;
  ExternalFlow = 0.0;
  InitialStandpipe = 0.0;
  Capacity = 0.00001;
  Priority = InitialPriority = 1;
  vXYZ.InitMatrix();
  vXYZ_drain.InitMatrix();
  ixx_unit = iyy_unit = izz_unit = 1.0;
  grainType = gtUNKNOWN; // This is the default

  type = el->GetAttributeValue("type");
  if      (type == "FUEL")     Type = ttFUEL;
  else if (type == "OXIDIZER") Type = ttOXIDIZER;
  else                         Type = ttUNKNOWN;

  element = el->FindElement("location");
  if (element)  vXYZ = element->FindElementTripletConvertTo("IN");
  else          cerr << "No location found for this tank." << endl;

  vXYZ_drain = vXYZ; // Set initial drain location to initial tank CG

  element = el->FindElement("drain_location");
  if (element)  {
    vXYZ_drain = element->FindElementTripletConvertTo("IN");
  }

  if (el->FindElement("radius"))
    Radius = el->FindElementValueAsNumberConvertTo("radius", "IN");
  if (el->FindElement("inertia_factor"))
    InertiaFactor = el->FindElementValueAsNumber("inertia_factor");
  if (el->FindElement("capacity"))
    Capacity = el->FindElementValueAsNumberConvertTo("capacity", "LBS");
  if (el->FindElement("contents"))
    InitialContents = Contents = el->FindElementValueAsNumberConvertTo("contents", "LBS");
  if (el->FindElement("temperature"))
    InitialTemperature = Temperature = el->FindElementValueAsNumber("temperature");
  if (el->FindElement("standpipe"))
    InitialStandpipe = Standpipe = el->FindElementValueAsNumberConvertTo("standpipe", "LBS");
  if (el->FindElement("priority"))
    InitialPriority = Priority = (int)el->FindElementValueAsNumber("priority");
  if (el->FindElement("density"))
    Density = el->FindElementValueAsNumberConvertTo("density", "LBS/GAL");
  if (el->FindElement("type"))
    strFuelName = el->FindElementValue("type");


  SetPriority( InitialPriority );     // this will also set the Selected flag

  if (Capacity == 0) {
    cerr << "Tank capacity must not be zero. Reset to 0.00001 lbs!" << endl;
    Capacity = 0.00001;
    Contents = 0.0;
  }
  if (Contents > Capacity) {
    cerr << "Tank content (" << Contents << " lbs) is greater than tank capacity ("
         << Capacity << " lbs) for tank " << tank_number
         << "! Did you accidentally swap contents and capacity?" << endl;
    throw("tank definition error");
  }

  PctFull = 100.0*Contents/Capacity;            // percent full; 0 to 100.0

  // Check whether this is a solid propellant "tank". Initialize it if true.

  element_Grain = el->FindElement("grain_config");
  if (element_Grain) {

    strGType = element_Grain->GetAttributeValue("type");
    if (strGType == "CYLINDRICAL")     grainType = gtCYLINDRICAL;
    else if (strGType == "ENDBURNING") grainType = gtENDBURNING;
    else if (strGType == "FUNCTION")   {
      grainType = gtFUNCTION;
      if (element_Grain->FindElement("ixx") != 0) {
        Element* element_ixx = element_Grain->FindElement("ixx");
        if (element_ixx->GetAttributeValue("unit") == "KG*M2") ixx_unit = 1.0/1.35594;
        if (element_ixx->FindElement("function") != 0) {
          function_ixx = new FGFunction(PropertyManager, element_ixx->FindElement("function"));
        }
      } else {
        throw("For tank "+to_string(TankNumber)+" and when grain_config is specified an ixx must be specified when the FUNCTION grain type is specified.");
      }

      if (element_Grain->FindElement("iyy")) {
        Element* element_iyy = element_Grain->FindElement("iyy");
        if (element_iyy->GetAttributeValue("unit") == "KG*M2") iyy_unit = 1.0/1.35594;
        if (element_iyy->FindElement("function") != 0) {
          function_iyy = new FGFunction(PropertyManager, element_iyy->FindElement("function"));
        }
      } else {
        throw("For tank "+to_string(TankNumber)+" and when grain_config is specified an iyy must be specified when the FUNCTION grain type is specified.");
      }

      if (element_Grain->FindElement("izz")) {
        Element* element_izz = element_Grain->FindElement("izz");
        if (element_izz->GetAttributeValue("unit") == "KG*M2") izz_unit = 1.0/1.35594;
        if (element_izz->FindElement("function") != 0) {
          function_izz = new FGFunction(PropertyManager, element_izz->FindElement("function"));
        }
      } else {
        throw("For tank "+to_string(TankNumber)+" and when grain_config is specified an izz must be specified when the FUNCTION grain type is specified.");
      }
    }
    else                               cerr << "Unknown propellant grain type specified" << endl;

    if (element_Grain->FindElement("length"))
      Length = element_Grain->FindElementValueAsNumberConvertTo("length", "IN");
    if (element_Grain->FindElement("bore_diameter"))
      InnerRadius = element_Grain->FindElementValueAsNumberConvertTo("bore_diameter", "IN")/2.0;

    // Initialize solid propellant values for debug and runtime use.

    switch (grainType) {
      case gtCYLINDRICAL:
        if (Radius <= InnerRadius) {
            std::stringstream error;
          error << "The bore diameter should be smaller than the total grain diameter!" << endl;
          throw std::runtime_error(error.str());
        }
        Volume = M_PI * Length * (Radius*Radius - InnerRadius*InnerRadius); // cubic inches
        break;
      case gtENDBURNING:
        Volume = M_PI * Length * Radius * Radius; // cubic inches
        break;
      case gtFUNCTION:
        Volume = 1;  // Volume is irrelevant for the FUNCTION type, but it can't be zero!
        break;
      case gtUNKNOWN:
          std::stringstream error;
        error << "Unknown grain type found in this rocket engine definition." << endl;
        throw std::runtime_error(error.str());
    }
    Density = (Contents*lbtoslug)/Volume; // slugs/in^3
  }

  CalculateInertias();

  if (Temperature != -9999.0)  InitialTemperature = Temperature = FahrenheitToCelsius(Temperature);
  Area = 40.0 * pow(Capacity/1975, 0.666666667);

  // A named fuel type will override a previous density value
  if (!strFuelName.empty()) Density = ProcessFuelName(strFuelName); 

  bind(PropertyManager);

  Debug(0);
}
Esempio n. 2
0
float CAtmosphereModelJSBSim::GetDewpointC (void)
{
  return (FahrenheitToCelsius (GetDewpointF ()));
}
Esempio n. 3
0
FGTank::FGTank(FGFDMExec* exec, Element* el, int tank_number)
                  : TankNumber(tank_number), Exec(exec)
{
  string token, strFuelName;
  Element* element;
  Element* element_Grain;
  Area = 1.0;
  Density = 6.6;
  InitialTemperature = Temperature = -9999.0;
  Ixx = Iyy = Izz = 0.0;
  InertiaFactor = 1.0;
  Radius = Contents = Standpipe = Length = InnerRadius = 0.0;
  PreviousUsed = 0.0;
  ExternalFlow = 0.0;
  InitialStandpipe = 0.0;
  Capacity = 0.00001;
  Priority = InitialPriority = 1;
  PropertyManager = Exec->GetPropertyManager();
  vXYZ.InitMatrix();
  vXYZ_drain.InitMatrix();

  type = el->GetAttributeValue("type");
  if      (type == "FUEL")     Type = ttFUEL;
  else if (type == "OXIDIZER") Type = ttOXIDIZER;
  else                         Type = ttUNKNOWN;

  element = el->FindElement("location");
  if (element)  vXYZ = element->FindElementTripletConvertTo("IN");
  else          cerr << "No location found for this tank." << endl;

  vXYZ_drain = vXYZ; // Set initial drain location to initial tank CG

  element = el->FindElement("drain_location");
  if (element)  {
    vXYZ_drain = element->FindElementTripletConvertTo("IN");
  }

  if (el->FindElement("radius"))
    Radius = el->FindElementValueAsNumberConvertTo("radius", "IN");
  if (el->FindElement("inertia_factor"))
    InertiaFactor = el->FindElementValueAsNumber("inertia_factor");
  if (el->FindElement("capacity"))
    Capacity = el->FindElementValueAsNumberConvertTo("capacity", "LBS");
  if (el->FindElement("contents"))
    InitialContents = Contents = el->FindElementValueAsNumberConvertTo("contents", "LBS");
  if (el->FindElement("temperature"))
    InitialTemperature = Temperature = el->FindElementValueAsNumber("temperature");
  if (el->FindElement("standpipe"))
    InitialStandpipe = Standpipe = el->FindElementValueAsNumberConvertTo("standpipe", "LBS");
  if (el->FindElement("priority"))
    InitialPriority = Priority = (int)el->FindElementValueAsNumber("priority");
  if (el->FindElement("density"))
    Density = el->FindElementValueAsNumberConvertTo("density", "LBS/GAL");
  if (el->FindElement("type"))
    strFuelName = el->FindElementValue("type");


  SetPriority( InitialPriority );     // this will also set the Selected flag

  if (Capacity == 0) {
    cerr << "Tank capacity must not be zero. Reset to 0.00001 lbs!" << endl;
    Capacity = 0.00001;
    Contents = 0.0;
  }
  if (Contents > Capacity) {
    cerr << "Tank content (" << Contents << " lbs) is greater than tank capacity ("
         << Capacity << " lbs) for tank " << tank_number
         << "! Did you accidentally swap contents and capacity?" << endl;
    throw("tank definition error");
  }

  PctFull = 100.0*Contents/Capacity;            // percent full; 0 to 100.0

  // Check whether this is a solid propellant "tank". Initialize it if true.

  grainType = gtUNKNOWN; // This is the default
  
  element_Grain = el->FindElement("grain_config");
  if (element_Grain) {

    strGType = element_Grain->GetAttributeValue("type");
    if (strGType == "CYLINDRICAL")     grainType = gtCYLINDRICAL;
    else if (strGType == "ENDBURNING") grainType = gtENDBURNING;
    else                               cerr << "Unknown propellant grain type specified" << endl;

    if (element_Grain->FindElement("length"))
      Length = element_Grain->FindElementValueAsNumberConvertTo("length", "IN");
    if (element_Grain->FindElement("bore_diameter"))
      InnerRadius = element_Grain->FindElementValueAsNumberConvertTo("bore_diameter", "IN")/2.0;

    // Initialize solid propellant values for debug and runtime use.

    switch (grainType) {
      case gtCYLINDRICAL:
        if (Radius <= InnerRadius) {
          cerr << "The bore diameter should be smaller than the total grain diameter!" << endl;
          exit(-1);
        }
        Volume = M_PI * Length * (Radius*Radius - InnerRadius*InnerRadius); // cubic inches
        break;
      case gtENDBURNING:
        Volume = M_PI * Length * Radius * Radius; // cubic inches
        break;
      case gtUNKNOWN:
        cerr << "Unknown grain type found in this rocket engine definition." << endl;
        exit(-1);
    }
    Density = (Contents*lbtoslug)/Volume; // slugs/in^3
  }

    CalculateInertias();

  string property_name, base_property_name;
  base_property_name = CreateIndexedPropertyName("propulsion/tank", TankNumber);
  property_name = base_property_name + "/contents-lbs";
  PropertyManager->Tie( property_name.c_str(), (FGTank*)this, &FGTank::GetContents,
                                       &FGTank::SetContents );
  property_name = base_property_name + "/pct-full";
  PropertyManager->Tie( property_name.c_str(), (FGTank*)this, &FGTank::GetPctFull);

  property_name = base_property_name + "/priority";
  PropertyManager->Tie( property_name.c_str(), (FGTank*)this, &FGTank::GetPriority,
                                       &FGTank::SetPriority );
  property_name = base_property_name + "/external-flow-rate-pps";
  PropertyManager->Tie( property_name.c_str(), (FGTank*)this, &FGTank::GetExternalFlow,
                                       &FGTank::SetExternalFlow );

  if (Temperature != -9999.0)  InitialTemperature = Temperature = FahrenheitToCelsius(Temperature);
  Area = 40.0 * pow(Capacity/1975, 0.666666667);

  // A named fuel type will override a previous density value
  if (!strFuelName.empty()) Density = ProcessFuelName(strFuelName); 

  Debug(0);
}