From 81313f4aa2f789e9e1b8a231730300dce03fe9c4 Mon Sep 17 00:00:00 2001
From: Bertrand Coconnier <bcoconni@users.sf.net>
Date: Sat, 24 Jul 2021 19:19:14 +0200
Subject: [PATCH] Sync'ed with JSBSim v1.1.8

- Always set useDefault to false when calling SGPropertyNode::tie()
- Mass flows can now be specified using SI unit (kg/s)
- Add a new property propulsion/fuel_freeze to freeze fuel consumption.
- Add a new flag DONT_EXECUTE_RUN_IC that can be specified to FGFDMExec::ResetToInitialConditions. When specified, this flag avoid calling FGFDMExec::RunIC when executing FGFDMExec::ResetToInitialConditions.
- Fix a bug in <linear_actuator> that resulted in erroneous output values when the input was oscillating around the zero value.
- Add an assert that forbids to set the value of FGPropertyValue when the property was specified with a minus sign.
- Fix the compatibility with recent versions of MinGW64
- Fix ws2tcpip.h casing for compilation on case sensitive OS.
- Improve the templating of FGPropertyManager::Tie().
- Expand FGParameterValue exception message (James Turner)
- TurboProp: Filters out negative powers when the propeller is not rotating
---
 src/FDM/JSBSim/FGFDMExec.cpp                  |   7 +-
 src/FDM/JSBSim/FGFDMExec.h                    |  11 +-
 .../JSBSim/input_output/FGPropertyManager.cpp | 101 +----------
 .../JSBSim/input_output/FGPropertyManager.h   | 167 +++++-------------
 src/FDM/JSBSim/input_output/FGXMLElement.cpp  |   1 +
 src/FDM/JSBSim/input_output/FGfdmSocket.cpp   |  12 +-
 src/FDM/JSBSim/math/FGFunction.h              |   2 +-
 src/FDM/JSBSim/math/FGMatrix33.cpp            |  16 +-
 src/FDM/JSBSim/math/FGMatrix33.h              |   4 +-
 src/FDM/JSBSim/math/FGParameterValue.h        |   2 +-
 src/FDM/JSBSim/math/FGPropertyValue.cpp       |   6 +-
 src/FDM/JSBSim/models/FGBuoyantForces.cpp     |  15 +-
 src/FDM/JSBSim/models/FGGasCell.cpp           |   4 +-
 src/FDM/JSBSim/models/FGPropulsion.cpp        |   2 +
 .../flight_control/FGLinearActuator.cpp       |  25 ++-
 .../models/flight_control/FGMagnetometer.cpp  |   2 +-
 .../JSBSim/models/propulsion/FGElectric.cpp   |   4 +-
 src/FDM/JSBSim/models/propulsion/FGPiston.cpp |  20 +--
 .../JSBSim/models/propulsion/FGTurboProp.cpp  |   5 +-
 19 files changed, 124 insertions(+), 282 deletions(-)

diff --git a/src/FDM/JSBSim/FGFDMExec.cpp b/src/FDM/JSBSim/FGFDMExec.cpp
index 7470d4ad7..e215d7ebb 100644
--- a/src/FDM/JSBSim/FGFDMExec.cpp
+++ b/src/FDM/JSBSim/FGFDMExec.cpp
@@ -604,7 +604,9 @@ void FGFDMExec::ResetToInitialConditions(int mode)
 {
   if (Constructing) return;
 
-  if (mode == 1) Output->SetStartNewOutput();
+  // mode flags
+
+  if (mode & START_NEW_OUTPUT) Output->SetStartNewOutput();
 
   InitializeModels();
 
@@ -613,7 +615,8 @@ void FGFDMExec::ResetToInitialConditions(int mode)
   else
     Setsim_time(0.0);
 
-  RunIC();
+  if (!(mode & DONT_EXECUTE_RUN_IC))
+    RunIC();
 }
 
 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
diff --git a/src/FDM/JSBSim/FGFDMExec.h b/src/FDM/JSBSim/FGFDMExec.h
index 7303d80e7..2d9d934a5 100644
--- a/src/FDM/JSBSim/FGFDMExec.h
+++ b/src/FDM/JSBSim/FGFDMExec.h
@@ -460,10 +460,15 @@ public:
   void Resume(void) {holding = false;}
   /// Returns true if the simulation is Holding (i.e. simulation time is not moving).
   bool Holding(void) {return holding;}
+  /// Mode flags for ResetToInitialConditions
+  static const int START_NEW_OUTPUT    = 0x1;
+  static const int DONT_EXECUTE_RUN_IC = 0x2;
   /** Resets the initial conditions object and prepares the simulation to run
-      again. If mode is set to 1 the output instances will take special actions
-      such as closing the current output file and open a new one with a
-      different name.
+      again. If the mode's first bit is set the output instances will take special actions
+      such as closing the current output file and open a new one with a different name.
+      If the second bit is set then RunIC() won't be executed, leaving it to the caller
+      to call RunIC(), e.g. in case the caller wants to set some other state like control
+      surface deflections which would've been reset.
       @param mode Sets the reset mode.*/
   void ResetToInitialConditions(int mode);
   /// Sets the debug level.
diff --git a/src/FDM/JSBSim/input_output/FGPropertyManager.cpp b/src/FDM/JSBSim/input_output/FGPropertyManager.cpp
index d79afdede..878e8a309 100644
--- a/src/FDM/JSBSim/input_output/FGPropertyManager.cpp
+++ b/src/FDM/JSBSim/input_output/FGPropertyManager.cpp
@@ -52,12 +52,10 @@ namespace JSBSim {
 
 void FGPropertyManager::Unbind(void)
 {
-    vector<SGPropertyNode_ptr>::iterator it;
+  for(auto& prop: tied_properties)
+    prop->untie();
 
-    for (it = tied_properties.begin();it < tied_properties.end();it++)
-        (*it)->untie();
-
-    tied_properties.clear();
+  tied_properties.clear();
 }
 
 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -73,7 +71,7 @@ string FGPropertyManager::mkPropertyName(string name, bool lowercase) {
     else if( isspace(name[i]) )
       name[i]='-';
   }
-  
+
   return name;
 }
 
@@ -324,95 +322,4 @@ void FGPropertyManager::Untie (const string &name)
   cerr << "Failed to untie property " << name << endl
        << "JSBSim is not the owner of this property." << endl;
 }
-
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-void FGPropertyManager::Tie (const string &name, bool *pointer)
-{
-  SGPropertyNode* property = root->getNode(name.c_str(), true);
-  if (!property) {
-    cerr << "Could not get or create property " << name << endl;
-    return;
-  }
-
-  if (!property->tie(SGRawValuePointer<bool>(pointer), false))
-    cerr << "Failed to tie property " << name << " to a pointer" << endl;
-  else {
-    tied_properties.push_back(property);
-    if (FGJSBBase::debug_lvl & 0x20) cout << name << endl;
-  }
-}
-
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-void FGPropertyManager::Tie (const string &name, int *pointer)
-{
-  SGPropertyNode* property = root->getNode(name.c_str(), true);
-  if (!property) {
-    cerr << "Could not get or create property " << name << endl;
-    return;
-  }
-
-  if (!property->tie(SGRawValuePointer<int>(pointer), false))
-    cerr << "Failed to tie property " << name << " to a pointer" << endl;
-  else {
-    tied_properties.push_back(property);
-    if (FGJSBBase::debug_lvl & 0x20) cout << name << endl;
-  }
-}
-
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-void FGPropertyManager::Tie (const string &name, long *pointer)
-{
-  SGPropertyNode* property = root->getNode(name.c_str(), true);
-  if (!property) {
-    cerr << "Could not get or create property " << name << endl;
-    return;
-  }
-
-  if (!property->tie(SGRawValuePointer<long>(pointer), false))
-    cerr << "Failed to tie property " << name << " to a pointer" << endl;
-  else {
-    tied_properties.push_back(property);
-    if (FGJSBBase::debug_lvl & 0x20) cout << name << endl;
-  }
-}
-
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-void FGPropertyManager::Tie (const string &name, float *pointer)
-{
-  SGPropertyNode* property = root->getNode(name.c_str(), true);
-  if (!property) {
-    cerr << "Could not get or create property " << name << endl;
-    return;
-  }
-
-  if (!property->tie(SGRawValuePointer<float>(pointer), false))
-    cerr << "Failed to tie property " << name << " to a pointer" << endl;
-  else {
-    tied_properties.push_back(property);
-    if (FGJSBBase::debug_lvl & 0x20) cout << name << endl;
-  }
-}
-
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-void FGPropertyManager::Tie (const string &name, double *pointer)
-{
-  SGPropertyNode* property = root->getNode(name.c_str(), true);
-  if (!property) {
-    cerr << "Could not get or create property " << name << endl;
-    return;
-  }
-
-  if (!property->tie(SGRawValuePointer<double>(pointer), false))
-    cerr << "Failed to tie property " << name << " to a pointer" << endl;
-  else {
-    tied_properties.push_back(property);
-    if (FGJSBBase::debug_lvl & 0x20) cout << name << endl;
-  }
-}
-
 } // namespace JSBSim
diff --git a/src/FDM/JSBSim/input_output/FGPropertyManager.h b/src/FDM/JSBSim/input_output/FGPropertyManager.h
index f3e766ea1..4015f9118 100644
--- a/src/FDM/JSBSim/input_output/FGPropertyManager.h
+++ b/src/FDM/JSBSim/input_output/FGPropertyManager.h
@@ -424,109 +424,31 @@ class FGPropertyManager
      */
     void Unbind (void);
 
-        // Templates cause ambiguity here
-
     /**
-     * Tie a property to an external bool variable.
+     * Tie a property to an external variable.
      *
      * The property's value will automatically mirror the variable's
      * value, and vice-versa, until the property is untied.
      *
      * @param name The property name to tie (full path).
      * @param pointer A pointer to the variable.
-     * @param useDefault true if any existing property value should be
-     *        copied to the variable; false if the variable should not
-     *        be modified; defaults to true.
      */
-    void
-    Tie (const std::string &name, bool *pointer);
+    template <typename T> void
+    Tie (const std::string &name, T *pointer)
+    {
+      SGPropertyNode* property = root->getNode(name.c_str(), true);
+      if (!property) {
+        cerr << "Could not get or create property " << name << endl;
+        return;
+      }
 
-
-    /**
-     * Tie a property to an external int variable.
-     *
-     * The property's value will automatically mirror the variable's
-     * value, and vice-versa, until the property is untied.
-     *
-     * @param name The property name to tie (full path).
-     * @param pointer A pointer to the variable.
-     * @param useDefault true if any existing property value should be
-     *        copied to the variable; false if the variable should not
-     *        be modified; defaults to true.
-     */
-    void
-    Tie (const std::string &name, int *pointer);
-
-
-    /**
-     * Tie a property to an external long variable.
-     *
-     * The property's value will automatically mirror the variable's
-     * value, and vice-versa, until the property is untied.
-     *
-     * @param name The property name to tie (full path).
-     * @param pointer A pointer to the variable.
-     * @param useDefault true if any existing property value should be
-     *        copied to the variable; false if the variable should not
-     *        be modified; defaults to true.
-     */
-    void
-    Tie (const std::string &name, long *pointer);
-
-
-    /**
-     * Tie a property to an external float variable.
-     *
-     * The property's value will automatically mirror the variable's
-     * value, and vice-versa, until the property is untied.
-     *
-     * @param name The property name to tie (full path).
-     * @param pointer A pointer to the variable.
-     * @param useDefault true if any existing property value should be
-     *        copied to the variable; false if the variable should not
-     *        be modified; defaults to true.
-     */
-    void
-    Tie (const std::string &name, float *pointer);
-
-    /**
-     * Tie a property to an external double variable.
-     *
-     * The property's value will automatically mirror the variable's
-     * value, and vice-versa, until the property is untied.
-     *
-     * @param name The property name to tie (full path).
-     * @param pointer A pointer to the variable.
-     * @param useDefault true if any existing property value should be
-     *        copied to the variable; false if the variable should not
-     *        be modified; defaults to true.
-     */
-    void
-    Tie (const std::string &name, double *pointer);
-
-//============================================================================
-//
-//  All of the following functions *must* be inlined, otherwise linker
-//  errors will result
-//
-//============================================================================
-
-    /* template <class V> void
-    Tie (const std::string &name, V (*getter)(), void (*setter)(V) = 0,
-           bool useDefault = true);
-
-    template <class V> void
-    Tie (const std::string &name, int index, V (*getter)(int),
-           void (*setter)(int, V) = 0, bool useDefault = true);
-
-    template <class T, class V> void
-    Tie (const std::string &name, T * obj, V (T::*getter)() const,
-           void (T::*setter)(V) = 0, bool useDefault = true);
-
-    template <class T, class V> void
-    Tie (const std::string &name, T * obj, int index,
-           V (T::*getter)(int) const, void (T::*setter)(int, V) = 0,
-           bool useDefault = true); */
+      if (!property->tie(SGRawValuePointer<T>(pointer), false))
+        cerr << "Failed to tie property " << name << " to a pointer" << endl;
+      else {
+        tied_properties.push_back(property);
+        if (FGJSBBase::debug_lvl & 0x20) cout << name << endl;
+      }
+    }
 
      /**
      * Tie a property to a pair of simple functions.
@@ -542,8 +464,8 @@ class FGPropertyManager
      * @param setter The setter function, or 0 if the value is unmodifiable.
      */
 
-    template <class V> inline void
-    Tie (const std::string &name, V (*getter)(), void (*setter)(V) = nullptr)
+    template <typename T> void
+    Tie (const std::string &name, T (*getter)(), void (*setter)(T) = nullptr)
     {
       SGPropertyNode* property = root->getNode(name.c_str(), true);
       if (!property) {
@@ -551,17 +473,17 @@ class FGPropertyManager
         return;
       }
 
-      if (!property->tie(SGRawValueFunctions<V>(getter, setter), false))
-        std::cerr << "Failed to tie property " << name << " to functions" << std::endl;
+      if (!property->tie(SGRawValueFunctions<T>(getter, setter), false))
+        std::cerr << "Failed to tie property " << name << " to functions"
+                  << std::endl;
       else {
-        if (setter == 0) property->setAttribute(SGPropertyNode::WRITE, false);
-        if (getter == 0) property->setAttribute(SGPropertyNode::READ, false);
+        if (!setter) property->setAttribute(SGPropertyNode::WRITE, false);
+        if (!getter) property->setAttribute(SGPropertyNode::READ, false);
         tied_properties.push_back(property);
         if (FGJSBBase::debug_lvl & 0x20) std::cout << name << std::endl;
       }
     }
 
-
     /**
      * Tie a property to a pair of indexed functions.
      *
@@ -577,8 +499,9 @@ class FGPropertyManager
      * @param getter The getter function, or 0 if the value is unreadable.
      * @param setter The setter function, or 0 if the value is unmodifiable.
      */
-    template <class V> inline void Tie (const std::string &name, int index, V (*getter)(int),
-                                void (*setter)(int, V) = nullptr)
+    template <typename T> void
+    Tie (const std::string &name, int index, T (*getter)(int),
+         void (*setter)(int, T) = nullptr)
     {
       SGPropertyNode* property = root->getNode(name.c_str(), true);
       if (!property) {
@@ -586,17 +509,18 @@ class FGPropertyManager
         return;
       }
 
-      if (!property->tie(SGRawValueFunctionsIndexed<V>(index, getter, setter), false))
-        std::cerr << "Failed to tie property " << name << " to indexed functions" << std::endl;
+      if (!property->tie(SGRawValueFunctionsIndexed<T>(index, getter, setter),
+                                                       false))
+        std::cerr << "Failed to tie property " << name << " to indexed functions"
+                  << std::endl;
       else {
-        if (setter == 0) property->setAttribute(SGPropertyNode::WRITE, false);
-        if (getter == 0) property->setAttribute(SGPropertyNode::READ, false);
+        if (!setter) property->setAttribute(SGPropertyNode::WRITE, false);
+        if (!getter) property->setAttribute(SGPropertyNode::READ, false);
         tied_properties.push_back(property);
         if (FGJSBBase::debug_lvl & 0x20) std::cout << name << std::endl;
       }
     }
 
-
     /**
      * Tie a property to a pair of object methods.
      *
@@ -613,9 +537,9 @@ class FGPropertyManager
      * @param setter The object's setter method, or 0 if the value is
      *        unmodifiable.
      */
-    template <class T, class V> inline void
+    template <class T, class V> void
     Tie (const std::string &name, T * obj, V (T::*getter)() const,
-           void (T::*setter)(V) = nullptr)
+         void (T::*setter)(V) = nullptr)
     {
       SGPropertyNode* property = root->getNode(name.c_str(), true);
       if (!property) {
@@ -624,10 +548,11 @@ class FGPropertyManager
       }
 
       if (!property->tie(SGRawValueMethods<T,V>(*obj, getter, setter), false))
-        std::cerr << "Failed to tie property " << name << " to object methods" << std::endl;
+        std::cerr << "Failed to tie property " << name << " to object methods"
+                  << std::endl;
       else {
-        if (setter == 0) property->setAttribute(SGPropertyNode::WRITE, false);
-        if (getter == 0) property->setAttribute(SGPropertyNode::READ, false);
+        if (!setter) property->setAttribute(SGPropertyNode::WRITE, false);
+        if (!getter) property->setAttribute(SGPropertyNode::READ, false);
         tied_properties.push_back(property);
         if (FGJSBBase::debug_lvl & 0x20) std::cout << name << std::endl;
       }
@@ -649,9 +574,9 @@ class FGPropertyManager
      * @param getter The getter method, or 0 if the value is unreadable.
      * @param setter The setter method, or 0 if the value is unmodifiable.
      */
-    template <class T, class V> inline void
+    template <class T, class V> void
     Tie (const std::string &name, T * obj, int index, V (T::*getter)(int) const,
-                         void (T::*setter)(int, V) = nullptr)
+         void (T::*setter)(int, V) = nullptr)
     {
       SGPropertyNode* property = root->getNode(name.c_str(), true);
       if (!property) {
@@ -659,15 +584,17 @@ class FGPropertyManager
         return;
       }
 
-      if (!property->tie(SGRawValueMethodsIndexed<T,V>(*obj, index, getter, setter), false))
-        std::cerr << "Failed to tie property " << name << " to indexed object methods" << std::endl;
+      if (!property->tie(SGRawValueMethodsIndexed<T,V>(*obj, index, getter, setter),
+                                                       false))
+        std::cerr << "Failed to tie property " << name
+                  << " to indexed object methods" << std::endl;
       else {
-        if (setter == 0) property->setAttribute(SGPropertyNode::WRITE, false);
-        if (getter == 0) property->setAttribute(SGPropertyNode::READ, false);
+        if (!setter) property->setAttribute(SGPropertyNode::WRITE, false);
+        if (!getter) property->setAttribute(SGPropertyNode::READ, false);
         tied_properties.push_back(property);
         if (FGJSBBase::debug_lvl & 0x20) std::cout << name << std::endl;
       }
-    }
+   }
 
     template <class T> simgear::PropertyObject<T>
     CreatePropertyObject(const std::string &path)
diff --git a/src/FDM/JSBSim/input_output/FGXMLElement.cpp b/src/FDM/JSBSim/input_output/FGXMLElement.cpp
index 01b5a00cb..094735d8a 100644
--- a/src/FDM/JSBSim/input_output/FGXMLElement.cpp
+++ b/src/FDM/JSBSim/input_output/FGXMLElement.cpp
@@ -156,6 +156,7 @@ Element::Element(const string& nm)
     convert["PA"]["LBS/FT2"] = 1.0/convert["LBS/FT2"]["PA"];
     // Mass flow
     convert["KG/MIN"]["LBS/MIN"] = convert["KG"]["LBS"];
+    convert["KG/SEC"]["LBS/SEC"] = convert["KG"]["LBS"];
     convert ["N/SEC"]["LBS/SEC"] = 0.224808943;
     convert ["LBS/SEC"]["N/SEC"] = 1.0/convert ["N/SEC"]["LBS/SEC"];
     // Fuel Consumption
diff --git a/src/FDM/JSBSim/input_output/FGfdmSocket.cpp b/src/FDM/JSBSim/input_output/FGfdmSocket.cpp
index ffc30b4a9..5fddce2b3 100644
--- a/src/FDM/JSBSim/input_output/FGfdmSocket.cpp
+++ b/src/FDM/JSBSim/input_output/FGfdmSocket.cpp
@@ -39,7 +39,7 @@ INCLUDES
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
 
 #if defined(_MSC_VER) || defined(__MINGW32__)
-#include <WS2tcpip.h>
+#include <ws2tcpip.h>
 #elif defined(__OpenBSD__)
 #include <sys/types.h>
 #include <sys/socket.h>
@@ -156,7 +156,7 @@ FGfdmSocket::FGfdmSocket(int port, int protocol)
   connected = false;
   Protocol = (ProtocolType)protocol;
   string ProtocolName;
- 
+
 #if defined(_MSC_VER) || defined(__MINGW32__)
   if (!LoadWinSockDLL(debug_lvl)) return;
 #endif
@@ -179,7 +179,7 @@ FGfdmSocket::FGfdmSocket(int port, int protocol)
   if (debug_lvl > 0)
     cout << "Creating input " << ProtocolName << " socket on port " << port
          << endl;
-  
+
   if (sckt != -1) {
     memset(&scktName, 0, sizeof(struct sockaddr_in));
     scktName.sin_family = AF_INET;
@@ -275,15 +275,15 @@ string FGfdmSocket::Receive(void)
     }
 #endif
   }
-  
+
   // this is for FGUDPInputSocket
   if (sckt >= 0 && Protocol == ptUDP) {
     struct sockaddr addr;
     socklen_t fromlen = sizeof addr;
     num_chars = recvfrom(sckt, buf, sizeof buf, 0, (struct sockaddr*)&addr, &fromlen);
-    if (num_chars != -1) data.append(buf, num_chars); 
+    if (num_chars != -1) data.append(buf, num_chars);
   }
-  
+
   return data;
 }
 
diff --git a/src/FDM/JSBSim/math/FGFunction.h b/src/FDM/JSBSim/math/FGFunction.h
index dcd9940f1..873af1e3f 100644
--- a/src/FDM/JSBSim/math/FGFunction.h
+++ b/src/FDM/JSBSim/math/FGFunction.h
@@ -826,7 +826,7 @@ protected:
   void CheckMinArguments(Element* el, unsigned int _min);
   void CheckMaxArguments(Element* el, unsigned int _max);
   void CheckOddOrEvenArguments(Element* el, OddEven odd_even);
-  std::string CreateOutputNode(Element* el, const string& Prefix);
+  std::string CreateOutputNode(Element* el, const std::string& Prefix);
 
 private:
   std::string Name;
diff --git a/src/FDM/JSBSim/math/FGMatrix33.cpp b/src/FDM/JSBSim/math/FGMatrix33.cpp
index 051aecf7f..f187d89d1 100644
--- a/src/FDM/JSBSim/math/FGMatrix33.cpp
+++ b/src/FDM/JSBSim/math/FGMatrix33.cpp
@@ -160,7 +160,7 @@ FGColumnVector3 FGMatrix33::GetEuler(void) const
 {
   FGColumnVector3 mEulerAngles;
   bool GimbalLock = false;
-  
+
   if (data[6] <= -1.0) {
     mEulerAngles(2) = 0.5*M_PI;
     GimbalLock = true;
@@ -176,7 +176,7 @@ FGColumnVector3 FGMatrix33::GetEuler(void) const
     mEulerAngles(1) = atan2(-data[5], data[4]);
   else
     mEulerAngles(1) = atan2(data[7], data[8]);
-  
+
   if (GimbalLock)
     mEulerAngles(3) = 0.0;
   else {
@@ -436,9 +436,9 @@ FGMatrix33 FGMatrix33::operator/(const double scalar) const
     Quot.data[2] = data[2] * tmp;
     Quot.data[5] = data[5] * tmp;
     Quot.data[8] = data[8] * tmp;
-  } else {
-      throw MatrixException{"Attempt to divide by zero in method FGMatrix33::operator/(const double scalar)"};
-  }
+  } else
+    throw MatrixException{"Attempt to divide by zero in method FGMatrix33::operator/(const double scalar)"};
+
   return Quot;
 }
 
@@ -457,9 +457,9 @@ FGMatrix33& FGMatrix33::operator/=(const double scalar)
     data[2] *= tmp;
     data[5] *= tmp;
     data[8] *= tmp;
-  } else {
-      throw MatrixException{"Attempt to divide by zero in method FGMatrix33::operator/=(const double scalar)"};
-  }
+  } else
+    throw MatrixException{"Attempt to divide by zero in method FGMatrix33::operator/=(const double scalar)"};
+
   return *this;
 }
 
diff --git a/src/FDM/JSBSim/math/FGMatrix33.h b/src/FDM/JSBSim/math/FGMatrix33.h
index 85fde1ea4..0ca03e1bc 100644
--- a/src/FDM/JSBSim/math/FGMatrix33.h
+++ b/src/FDM/JSBSim/math/FGMatrix33.h
@@ -65,12 +65,10 @@ CLASS DOCUMENTATION
 DECLARATION: MatrixException
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
 
-// changed by James to inherit std::runtime_error, so that if this
-// gets thrown, we can actually catch it.
 class MatrixException : public std::runtime_error
 {
 public:
-    MatrixException(const std::string& msg) : std::runtime_error{msg} { }
+  MatrixException(const std::string& msg) : std::runtime_error{msg} { }
 };
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
diff --git a/src/FDM/JSBSim/math/FGParameterValue.h b/src/FDM/JSBSim/math/FGParameterValue.h
index 733608ab3..cbb2ab9a4 100644
--- a/src/FDM/JSBSim/math/FGParameterValue.h
+++ b/src/FDM/JSBSim/math/FGParameterValue.h
@@ -71,7 +71,7 @@ public:
            << "The element <" << el->GetName()
            << "> must either contain a value number or a property name."
            << endl;
-      throw invalid_argument("Illegal argument");
+      throw invalid_argument("FGParameterValue: Illegal argument defining: " + el->GetName());
     }
 
     Construct(value, pm);
diff --git a/src/FDM/JSBSim/math/FGPropertyValue.cpp b/src/FDM/JSBSim/math/FGPropertyValue.cpp
index df1b7ea51..91473f0d3 100644
--- a/src/FDM/JSBSim/math/FGPropertyValue.cpp
+++ b/src/FDM/JSBSim/math/FGPropertyValue.cpp
@@ -29,8 +29,9 @@ Purpose: Stores property values
 INCLUDES
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
 
+#include <assert.h>
+
 #include "FGPropertyValue.h"
-#include "input_output/FGPropertyManager.h"
 
 namespace JSBSim {
 
@@ -80,6 +81,9 @@ double FGPropertyValue::GetValue(void) const
 
 void FGPropertyValue::SetValue(double value)
 {
+  // SetValue() ignores the Sign flag. So make sure it is never called with a
+  // negative sign.
+  assert(Sign == 1);
   GetNode()->setDoubleValue(value);
 }
 
diff --git a/src/FDM/JSBSim/models/FGBuoyantForces.cpp b/src/FDM/JSBSim/models/FGBuoyantForces.cpp
index b9474a9e7..ec1dfe729 100644
--- a/src/FDM/JSBSim/models/FGBuoyantForces.cpp
+++ b/src/FDM/JSBSim/models/FGBuoyantForces.cpp
@@ -241,20 +241,19 @@ string FGBuoyantForces::GetBuoyancyValues(const string& delimeter)
 
 void FGBuoyantForces::bind(void)
 {
-  typedef double (FGBuoyantForces::*PGF)(int) const;
-  typedef void   (FGBuoyantForces::*PSF)(int, double);
+  using PSF = void (FGBuoyantForces::*)(int, double);
   PropertyManager->Tie("moments/l-buoyancy-lbsft", this, eL,
-                       (PGF)&FGBuoyantForces::GetMoments, (PSF)nullptr);
+                       &FGBuoyantForces::GetMoments, (PSF)nullptr);
   PropertyManager->Tie("moments/m-buoyancy-lbsft", this, eM,
-                       (PGF)&FGBuoyantForces::GetMoments, (PSF)nullptr);
+                       &FGBuoyantForces::GetMoments, (PSF)nullptr);
   PropertyManager->Tie("moments/n-buoyancy-lbsft", this, eN,
-                       (PGF)&FGBuoyantForces::GetMoments, (PSF)nullptr);
+                       &FGBuoyantForces::GetMoments, (PSF)nullptr);
   PropertyManager->Tie("forces/fbx-buoyancy-lbs", this, eX,
-                       (PGF)&FGBuoyantForces::GetForces, (PSF)nullptr);
+                       &FGBuoyantForces::GetForces, (PSF)nullptr);
   PropertyManager->Tie("forces/fby-buoyancy-lbs", this, eY,
-                       (PGF)&FGBuoyantForces::GetForces, (PSF)nullptr);
+                       &FGBuoyantForces::GetForces, (PSF)nullptr);
   PropertyManager->Tie("forces/fbz-buoyancy-lbs", this, eZ,
-                       (PGF)&FGBuoyantForces::GetForces, (PSF)nullptr);
+                       &FGBuoyantForces::GetForces, (PSF)nullptr);
 }
 
 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
diff --git a/src/FDM/JSBSim/models/FGGasCell.cpp b/src/FDM/JSBSim/models/FGGasCell.cpp
index ebc19e8e4..3aecd5c05 100644
--- a/src/FDM/JSBSim/models/FGGasCell.cpp
+++ b/src/FDM/JSBSim/models/FGGasCell.cpp
@@ -195,7 +195,7 @@ FGGasCell::FGGasCell(FGFDMExec* exec, Element* el, unsigned int num,
 
   property_name = base_property_name + "/max_volume-ft3";
   PropertyManager->Tie( property_name.c_str(), &MaxVolume);
-  PropertyManager->GetNode()->SetWritable( property_name);
+  PropertyManager->GetNode()->SetWritable( property_name, false );
   property_name = base_property_name + "/temp-R";
   PropertyManager->Tie( property_name.c_str(), &Temperature);
   property_name = base_property_name + "/pressure-psf";
@@ -623,7 +623,7 @@ FGBallonet::FGBallonet(FGFDMExec* exec, Element* el, unsigned int num,
 
   property_name = base_property_name + "/max_volume-ft3";
   PropertyManager->Tie( property_name, &MaxVolume);
-  PropertyManager->GetNode()->SetWritable( property_name);
+  PropertyManager->GetNode()->SetWritable( property_name, false );
 
   property_name = base_property_name + "/temp-R";
   PropertyManager->Tie( property_name, &Temperature);
diff --git a/src/FDM/JSBSim/models/FGPropulsion.cpp b/src/FDM/JSBSim/models/FGPropulsion.cpp
index 6c25b3205..685498b0a 100644
--- a/src/FDM/JSBSim/models/FGPropulsion.cpp
+++ b/src/FDM/JSBSim/models/FGPropulsion.cpp
@@ -802,6 +802,7 @@ void FGPropulsion::bind(void)
 {
   typedef double (FGPropulsion::*PMF)(int) const;
   typedef int (FGPropulsion::*iPMF)(void) const;
+  typedef bool (FGPropulsion::*bPMF)(void) const;
 
   IsBound = true;
   PropertyManager->Tie("propulsion/set-running", this, (iPMF)0, &FGPropulsion::InitRunning);
@@ -827,6 +828,7 @@ void FGPropulsion::bind(void)
   TotalOxidizerQuantity = PropertyManager->CreatePropertyObject<double>("propulsion/total-oxidizer-lbs");
   refuel = PropertyManager->CreatePropertyObject<bool>("propulsion/refuel");
   dump = PropertyManager->CreatePropertyObject<bool>("propulsion/fuel_dump");
+  PropertyManager->Tie("propulsion/fuel_freeze", this, (bPMF)nullptr, &FGPropulsion::SetFuelFreeze);
 }
 
 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
diff --git a/src/FDM/JSBSim/models/flight_control/FGLinearActuator.cpp b/src/FDM/JSBSim/models/flight_control/FGLinearActuator.cpp
index 07e8e292d..1f5223585 100644
--- a/src/FDM/JSBSim/models/flight_control/FGLinearActuator.cpp
+++ b/src/FDM/JSBSim/models/flight_control/FGLinearActuator.cpp
@@ -1,5 +1,5 @@
 /* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
- * 
+ *
 Module:       FGLinearActuator.cpp
 Author:       Adriano Bassignana
 Date started: 2019-01-03
@@ -43,11 +43,11 @@ INCLUDES
 using namespace std;
 
 namespace JSBSim {
-    
+
 /* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 CLASS IMPLEMENTATION
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
-    
+
 FGLinearActuator::FGLinearActuator(FGFCS* fcs, Element* element)
   : FGFCSComponent(fcs, element)
 {
@@ -141,7 +141,7 @@ FGLinearActuator::FGLinearActuator(FGFCS* fcs, Element* element)
 
   Debug(0);
 }
-    
+
 // %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
 FGLinearActuator::~FGLinearActuator()
@@ -184,16 +184,11 @@ bool FGLinearActuator::Run(void )
         }
         if ((versus == 0) || (versus == direction)) {
           inputMem = Input;
-          if (direction != 0) {
-            if (abs(inputDelta) >= (module*rate)) {
-              if (direction > 0) {
-                countSpin++;
-                direction = 0;
-              } else if (direction < 0) {
-                countSpin--;
-                direction = 0;
-              }
-            }
+          if (abs(inputDelta) >= (module*rate)) {
+            if (inputDelta < 0)
+              countSpin++;
+            else
+              countSpin--;
           }
         } else if ((versus != 0) && (direction != 0) && (versus != direction)) {
           inputLast += inputDelta;
@@ -207,7 +202,7 @@ bool FGLinearActuator::Run(void )
   }
 
   if (lag > 0.0) {
-    double input = Output; 
+    double input = Output;
     Output = ca * (input + previousLagInput) + previousLagOutput * cb;
     previousLagInput = input;
     previousLagOutput = Output;
diff --git a/src/FDM/JSBSim/models/flight_control/FGMagnetometer.cpp b/src/FDM/JSBSim/models/flight_control/FGMagnetometer.cpp
index bee2e7b6e..14218bde0 100644
--- a/src/FDM/JSBSim/models/flight_control/FGMagnetometer.cpp
+++ b/src/FDM/JSBSim/models/flight_control/FGMagnetometer.cpp
@@ -75,7 +75,7 @@ FGMagnetometer::FGMagnetometer(FGFCS* fcs, Element* element)
   time_t rawtime;
   time( &rawtime );
   struct tm ptm;
-  #ifdef _MSC_VER
+  #if defined(_MSC_VER) || defined(__MINGW32__)
   gmtime_s(&ptm, &rawtime);
   #else
   gmtime_r(&rawtime, &ptm);
diff --git a/src/FDM/JSBSim/models/propulsion/FGElectric.cpp b/src/FDM/JSBSim/models/propulsion/FGElectric.cpp
index f43506407..06d01a989 100644
--- a/src/FDM/JSBSim/models/propulsion/FGElectric.cpp
+++ b/src/FDM/JSBSim/models/propulsion/FGElectric.cpp
@@ -90,12 +90,12 @@ void FGElectric::Calculate(void)
   if (Thruster->GetType() == FGThruster::ttPropeller) {
     ((FGPropeller*)Thruster)->SetAdvance(in.PropAdvance[EngineNumber]);
     ((FGPropeller*)Thruster)->SetFeather(in.PropFeather[EngineNumber]);
-  } 
+  }
 
   RPM = Thruster->GetRPM() * Thruster->GetGearRatio();
 
   HP = PowerWatts * in.ThrottlePos[EngineNumber] / hptowatts;
-  
+
   LoadThrusterInputs();
   // Filters out negative powers when the propeller is not rotating.
   double power = HP * hptoftlbssec;
diff --git a/src/FDM/JSBSim/models/propulsion/FGPiston.cpp b/src/FDM/JSBSim/models/propulsion/FGPiston.cpp
index edcbead4a..38813b556 100644
--- a/src/FDM/JSBSim/models/propulsion/FGPiston.cpp
+++ b/src/FDM/JSBSim/models/propulsion/FGPiston.cpp
@@ -124,7 +124,7 @@ FGPiston::FGPiston(FGFDMExec* exec, Element* el, int engine_number, struct Input
   bTakeoffBoost = false;
   TakeoffBoost = 0.0;   // Default to no extra takeoff-boost
   BoostLossFactor = 0.0;   // Default to free boost
-  
+
   int i;
   for (i=0; i<FG_MAX_BOOST_SPEEDS; i++) {
     RatedBoost[i] = 0.0;
@@ -142,7 +142,7 @@ FGPiston::FGPiston(FGFDMExec* exec, Element* el, int engine_number, struct Input
 
   // Read inputs from engine data file where present.
 
-  if (el->FindElement("minmp")) 
+  if (el->FindElement("minmp"))
     MinManifoldPressure_inHg = el->FindElementValueAsNumberConvertTo("minmp","INHG");
   if (el->FindElement("maxmp"))
     MaxManifoldPressure_inHg = el->FindElementValueAsNumberConvertTo("maxmp","INHG");
@@ -309,7 +309,7 @@ FGPiston::FGPiston(FGFDMExec* exec, Element* el, int engine_number, struct Input
     Z_airbox = (standard_pressure *Ze / maxMAP) - Ze; // impedence of airbox
   }
   // Constant for Throttle impedence
-  Z_throttle=(PeakMeanPistonSpeed_fps/((IdleRPM * Stroke) / 360))*(standard_pressure/minMAP - 1) - Z_airbox; 
+  Z_throttle=(PeakMeanPistonSpeed_fps/((IdleRPM * Stroke) / 360))*(standard_pressure/minMAP - 1) - Z_airbox;
   //  Z_throttle=(MaxRPM/IdleRPM )*(standard_pressure/minMAP+2); // Constant for Throttle impedence
 
 // Default tables if not provided in the configuration file
@@ -518,9 +518,7 @@ void FGPiston::Calculate(void)
   }
 
   LoadThrusterInputs();
-  // Filters out negative powers.
-  // TODO: static_friction_HP should not be taken into account while the engine
-  // is not started.
+  // Filters out negative powers when the propeller is not rotating.
   double power = HP * hptoftlbssec;
   if (RPM <= 0.1) power = max(power, 0.0);
   Thruster->Calculate(power);
@@ -533,7 +531,7 @@ void FGPiston::Calculate(void)
 double FGPiston::CalcFuelNeed(void)
 {
   FuelExpended = FuelFlowRate * in.TotalDeltaT;
-  if (!Starved) FuelUsedLbs += FuelExpended; 
+  if (!Starved) FuelUsedLbs += FuelExpended;
   return FuelExpended;
 }
 
@@ -594,7 +592,7 @@ void FGPiston::doEngineStartup(void)
   if ( Running ) {
     if (!spark || !fuel)    Running = false;
     if (RPM < IdleRPM*0.8 ) Running = false;
-  } else { // !Running  
+  } else { // !Running
     if ( spark && fuel) {     // start the engine if revs high enough
       if (RPM > IdleRPM*0.8)  // This allows us to in-air start
         Running = true;       // when windmilling
@@ -705,7 +703,7 @@ void FGPiston::doMAP(void)
   } else {
       BoostLossHP = 0;
   }
-  
+
   // And set the value in American units as well
   ManifoldPressure_inHg = MAP / inhgtopa;
 }
@@ -800,14 +798,14 @@ void FGPiston::doEnginePower(void)
   } else {
     // Power output when the engine is not running
     double torque, k_torque, rpm;  // Convienience term for use in the calculations
-    
+
     rpm = RPM < 1.0 ? 1.0 : RPM;
     if (Cranking) {
       if(RPM<StarterRPM) k_torque = 1.0-RPM/(StarterRPM);
       else k_torque = 0;
       torque = StarterTorque*k_torque*StarterGain;
       IndicatedHorsePower = torque * rpm / 5252;
-     } 
+     }
   }
 
   // Constant is (1/2) * 60 * 745.7
diff --git a/src/FDM/JSBSim/models/propulsion/FGTurboProp.cpp b/src/FDM/JSBSim/models/propulsion/FGTurboProp.cpp
index 5aba0fcd6..4cad50b40 100644
--- a/src/FDM/JSBSim/models/propulsion/FGTurboProp.cpp
+++ b/src/FDM/JSBSim/models/propulsion/FGTurboProp.cpp
@@ -291,7 +291,10 @@ void FGTurboProp::Calculate(void)
   }
  
   LoadThrusterInputs();
-  Thruster->Calculate(HP * hptoftlbssec);
+  // Filters out negative powers when the propeller is not rotating.
+  double power = HP * hptoftlbssec;
+  if (RPM <= 0.1) power = max(power, 0.0);
+  Thruster->Calculate(power);
 
   RunPostFunctions();
 }