# Path: auxi/core/objects.py
# class Object(object):
#     """
#     Base class for all auxi classes.
#     """
# 
#     def __str__(self):
#         o = json.loads(jsonpickle.encode(self))
#         result = json.dumps(o, sort_keys=True, indent=4,
#                             separators=(',', ': '))
#         return result
# 
#     def __hash__(self):
#         return hash(str(self))
# 
#     def _validate_params_(self):
#         pass
# 
#     def _init(self):
#         pass
# 
#     def write(self, path):
#         with open(path, 'w') as file:
#             file.write(str(self))
# 
#     @staticmethod
#     def read(path):
#         with open(path, 'r') as file:
#             s = file.read()
#         result = jsonpickle.decode(s)
#         result._init()
#         return result
# 
# class NamedObject(Object):
#     """
#     Base class for all auxi classes requiring a name and description.
# 
#     :param name: the object's name
#     :param description: the object's description
#     """
# 
#     def __init__(self, name, description=None):
#         self.name = name
#         self.description = description
# 
#     def _validate_params_(self, name, description):
#         # TODO: Enforce name format.
#         pass
# 
# Path: auxi/tools/transportphenomena/dimensionlessquantities.py
# def Gr(L: float, Ts: float, Tf: float, beta: float, nu: float, g: float):
# def Pr(nu: float, alpha: float) -> float:
# def Re(L: float, v: float, nu: float) -> float:
# def Ra(L: float, Ts: float, Tf: float, alpha: float, beta: float, nu: float
#        ) -> float:
# def Nu(L: float, h: float, k: float) -> float:
# def Sh(L: float, h: float, D: float) -> float:
# 
# Path: auxi/tools/physicalconstants.py
# G = 6.67403E-11
# N_A = 6.02214076E23
# F = 96485.33212
# R = 8.314462618
# T_NTP = 293.15
# P_NTP = 101325.0
# T_STP = 273.15
# P_STP = 100000.0


from math import radians, cos
from matplotlib import pyplot as plt
from matplotlib.patches import Rectangle
from auxi.core.objects import Object, NamedObject
from auxi.tools.transportphenomena import dimensionlessquantities as dq
from auxi.tools import physicalconstants as const
        :param Tf: [K] bulk fluid temperature

        :returns: float
        """

        Tf = statef['T']
        thetar = radians(theta)

        if self._isgas:
            self.Tr = Ts - 0.38 * (Ts - Tf)
            beta = self._fluid.beta(T=Tf)
        else:  # for liquids
            self.Tr = Ts - 0.5 * (Ts - Tf)
            beta = self._fluid.beta(T=self.Tr)

        if Ts > Tf:  # hot surface
            if 0.0 < theta < 45.0:
                g = const.g*cos(thetar)
            else:
                g = const.g
        else:  # cold surface
            if -45.0 < theta < 0.0:
                g = const.g*cos(thetar)
            else:
                g = const.g

        nu = self._fluid.nu(T=self.Tr)
        alpha = self._fluid.alpha(T=self.Tr)

        Gr = dq.Gr(L, Ts, Tf, beta, nu, g)

# Path: auxi/core/objects.py
# class Object(object):
#     """
#     Base class for all auxi classes.
#     """
# 
#     def __str__(self):
#         o = json.loads(jsonpickle.encode(self))
#         result = json.dumps(o, sort_keys=True, indent=4,
#                             separators=(',', ': '))
#         return result
# 
#     def __hash__(self):
#         return hash(str(self))
# 
#     def _validate_params_(self):
#         pass
# 
#     def _init(self):
#         pass
# 
#     def write(self, path):
#         with open(path, 'w') as file:
#             file.write(str(self))
# 
#     @staticmethod
#     def read(path):
#         with open(path, 'r') as file:
#             s = file.read()
#         result = jsonpickle.decode(s)
#         result._init()
#         return result
# 
# class NamedObject(Object):
#     """
#     Base class for all auxi classes requiring a name and description.
# 
#     :param name: the object's name
#     :param description: the object's description
#     """
# 
#     def __init__(self, name, description=None):
#         self.name = name
#         self.description = description
# 
#     def _validate_params_(self, name, description):
#         # TODO: Enforce name format.
#         pass
# 
# Path: auxi/tools/transportphenomena/dimensionlessquantities.py
# def Gr(L: float, Ts: float, Tf: float, beta: float, nu: float, g: float):
# def Pr(nu: float, alpha: float) -> float:
# def Re(L: float, v: float, nu: float) -> float:
# def Ra(L: float, Ts: float, Tf: float, alpha: float, beta: float, nu: float
#        ) -> float:
# def Nu(L: float, h: float, k: float) -> float:
# def Sh(L: float, h: float, D: float) -> float:
# 
# Path: auxi/tools/physicalconstants.py
# G = 6.67403E-11
# N_A = 6.02214076E23
# F = 96485.33212
# R = 8.314462618
# T_NTP = 293.15
# P_NTP = 101325.0
# T_STP = 273.15
# P_STP = 100000.0


# Path: auxi/tools/transportphenomena/heattransfer/naturalconvection.py
from math import radians, cos
from matplotlib import pyplot as plt
from matplotlib.patches import Rectangle
from auxi.core.objects import Object, NamedObject
from auxi.tools.transportphenomena import dimensionlessquantities as dq
from auxi.tools import physicalconstants as const

        :param Tf: [K] bulk fluid temperature

        :returns: float
        """

        Tf = statef['T']
        thetar = radians(theta)

        if self._isgas:
            self.Tr = Ts - 0.38 * (Ts - Tf)
            beta = self._fluid.beta(T=Tf)
        else:  # for liquids
            self.Tr = Ts - 0.5 * (Ts - Tf)
            beta = self._fluid.beta(T=self.Tr)

        if Ts > Tf:  # hot surface
            if 0.0 < theta < 45.0:
                g = const.g*cos(thetar)
            else:
                g = const.g
        else:  # cold surface
            if -45.0 < theta < 0.0:
                g = const.g*cos(thetar)
            else:
                g = const.g

        nu = self._fluid.nu(T=self.Tr)
        alpha = self._fluid.alpha(T=self.Tr)

        Gr = dq.Gr(L, Ts, Tf, beta, nu, g)

        Pr = dq.Pr(nu, alpha)