示例#1
0
def curve_constant_humidity_ratio(
        dry_temps: Iterable[float],
        rh_percentage: Union[float, Iterable[float]]=100.,
        p_atm_kpa: float=PRESSURE_STD_ATM_KPA, mode_sat=1) -> List[float]:
    """Generate a curve (numpy array) of constant humidity ratio."""
    if isinstance(rh_percentage, Iterable):
        return [1000 * humidity_ratio(
            saturation_pressure_water_vapor(t, mode=mode_sat)
            * rh / 100., p_atm_kpa)
                for t, rh in zip(dry_temps, rh_percentage)]
    return [1000 * humidity_ratio(
        saturation_pressure_water_vapor(t, mode=mode_sat)
        * rh_percentage / 100., p_atm_kpa)
            for t in dry_temps]
示例#2
0
    def test_density_at_saturation(self):
        """Density of saturated humid air from dry bulb temperature."""
        # TODO finish test specific_volume

        # vol_m3_kg = specific_volume(
        #     dry_temp_c, p_sat, p_atm_kpa=PRESSURE_STD_ATM_KPA)
        # print(dry_temp_c, p_sat, p_sat_ref, vol_m3_kg, 1/vol_m3_kg, d_ref)
        # self.assertAlmostEqual(1 / vol_m3_kg, d_ref, delta=1)

        from psychrochart.equations import (
            PRESSURE_STD_ATM_KPA, saturation_pressure_water_vapor,
            specific_volume)

        press = PRESSURE_STD_ATM_KPA
        for t, (ps_ref, dens_ref) in TEMP_PRESS_PA_DENS_G_KG.items():
            # dens_ref_kg_m3 = dens_ref / 1000.

            psat = saturation_pressure_water_vapor(t, mode=1)
            # xmax = humidity_ratio(psat)
            vol_psat = specific_volume(t, psat, p_atm_kpa=press)
            vol_p0 = specific_volume(t, 0, p_atm_kpa=press)
            print('DEB', t, dens_ref, vol_psat, vol_p0, 1/vol_psat, 1/vol_p0)
            dens_kg_m3 = 1 / vol_psat - 1 / vol_p0
            print(dens_kg_m3)

            self.assertAlmostEqual(psat, ps_ref / 1000, delta=27)
示例#3
0
def curve_constant_humidity_ratio(
        dry_temps: List[float], rh_percentage: float=100.,
        p_atm_kpa: float=PRESSURE_STD_ATM_KPA, mode_sat=1) -> List[float]:
    """Generate a curve (numpy array) of constant humidity ratio."""
    return [1000 * humidity_ratio(
        saturation_pressure_water_vapor(t, mode=mode_sat)
        * rh_percentage / 100., p_atm_kpa)
            for t in dry_temps]
示例#4
0
    def test_press_sat_mode_3(self):
        """Saturation pressure in kPa from dry bulb temperature. Mode 3."""
        from psychrochart.equations import saturation_pressure_water_vapor

        mode = 3
        [self._error_compare(
            saturation_pressure_water_vapor(t, mode=mode),
            DRY_TEMP_PSAT_KPA[t], self.pressure_error * max(.8, t / 50),
            "M3 - Saturation Pressure error > {} kPa: T={}, est={}")
            for t in sorted(DRY_TEMP_PSAT_KPA)]
示例#5
0
    def test_max_specific_humid(self):
        """Max Specific humidity from dry bulb temperature."""
        from psychrochart.equations import (
            humidity_ratio, saturation_pressure_water_vapor)

        for t, (ps_ref, xmax_ref) in TEMP_SAT_PRESS_HUMID_RATIO.items():
            psat = saturation_pressure_water_vapor(t)
            xmax = humidity_ratio(psat)
            # print(t, psat, ps_ref / 1000, xmax, xmax_ref)
            self.assertAlmostEqual(psat, ps_ref / 1000, delta=0.05)
            self.assertAlmostEqual(xmax, xmax_ref, delta=0.0005)
示例#6
0
    def test_press_sat_abs_error(self):
        """Saturation pressure in kPa from dry bulb temperature. Sum error."""
        from psychrochart.equations import saturation_pressure_water_vapor

        for mode in [1, 2, 3]:
            errors = [saturation_pressure_water_vapor(t, mode=mode)
                      - DRY_TEMP_PSAT_KPA[t]
                      for t in sorted(DRY_TEMP_PSAT_KPA)]

            self._error_compare(
                sum(errors), 0, self.total_pressure_error,
                "Saturation Pressure error > {} kPa ({}) -> {}")
示例#7
0
    def test_dew_point_temperature(self):
        """Dew point temperature testing."""
        from psychrochart.equations import (
            saturation_pressure_water_vapor, dew_point_temperature)
        from psychrochart.util import f_range

        temps = f_range(-20, 60, 1)
        for t in temps:
            p_sat = saturation_pressure_water_vapor(t)
            # w_sat = humidity_ratio(p_sat, p_atm_kpa=p_atm)
            temp_dp_sat = dew_point_temperature(p_sat)
            if temp_dp_sat < 0:
                self.assertAlmostEqual(temp_dp_sat, t, delta=3)
            else:
                self.assertAlmostEqual(temp_dp_sat, t, delta=2.5)
示例#8
0
    def plot_vertical_dry_bulb_temp_line(
            self, temp: float,
            style: dict=None,
            label: str=None,
            reverse: bool=False,
            **label_params) -> None:
        """Append a vertical line from w_min to w_sat."""
        w_max = 1000 * humidity_ratio(
            saturation_pressure_water_vapor(temp), self.p_atm_kpa)

        style_curve = style or self.d_config.get("constant_dry_temp")
        path_y = [w_max, self.w_min] if reverse else [self.w_min, w_max]
        curve = PsychroCurve(
            [temp, temp], path_y, style=style_curve, logger=self._logger)
        curve.plot(self.axes)
        if label is not None:
            curve.add_label(self.axes, label, **label_params)
示例#9
0
    def test_density_water_vapor(self):
        from psychrochart.equations import (
            density_water_vapor, saturation_pressure_water_vapor)

        for dry_temp_c, (p_sat_ref, d_ref) in TEMP_SAT_PRES_DENSITY.items():
            p_sat_ref /= 1000.  # to kPa
            p_sat = saturation_pressure_water_vapor(dry_temp_c)
            # Check with 5% error at 100 ºC
            self.assertAlmostEqual(
                p_sat, p_sat_ref,
                delta=p_sat_ref / 20 * max(.5, dry_temp_c / 100))

            dens_kg_m3 = density_water_vapor(p_sat, dry_temp_c)
            # print('DBT {} ºC -> {:.3f} (ref: {})  - Err={} %'.format(
            #     dry_temp_c, dens_kg_m3, d_ref,
            #     round(100 * (dens_kg_m3 - d_ref) / d_ref, 1)))
            self.assertAlmostEqual(
                dens_kg_m3, d_ref,
                delta=max(0.005, d_ref / 20) * max(.2, dry_temp_c / 100))
示例#10
0
    def test_enthalpy_moist_air(self):
        """Check the enthalpy of humid air."""
        from psychrochart.equations import (
            PRESSURE_STD_ATM_KPA, saturation_pressure_water_vapor,
            humidity_ratio, enthalpy_moist_air)

        # From http://www.engineeringtoolbox.com/enthalpy-moist-air-d_683.html
        # Check the enthalpy of humid air at 25ºC with specific
        # moisture content x = 0.0203 kg/kg (saturation).
        press = PRESSURE_STD_ATM_KPA
        dry_temp_c, w_kg_kga = 25, 0.0203

        p_sat = saturation_pressure_water_vapor(dry_temp_c)
        w_max = humidity_ratio(p_sat, press)
        ratio_humid = w_kg_kga / w_max
        p_w_kpa = ratio_humid * p_sat

        h_m = enthalpy_moist_air(dry_temp_c, p_w_kpa, press)
        h_m_bis = enthalpy_moist_air(dry_temp_c, p_w_kpa, press)
        self.assertEqual(h_m, h_m_bis)
        self.assertEqual(round(h_m, 1), 76.9)
示例#11
0
    def _make_chart_data(self,
                         styles: Union[dict, str]=None,
                         zones_file: Union[dict, str]=None) -> None:
        """Generate the data to plot the psychrometric chart."""
        # Get styling
        config = load_config(styles)
        self.d_config = config
        self.temp_step = config['limits']['step_temp']

        self.figure_params = config['figure']
        self.dbt_min, self.dbt_max = config['limits']['range_temp_c']
        self.w_min, self.w_max = config['limits']['range_humidity_g_kg']
        self.chart_params = config['chart_params']

        # Base pressure
        if config['limits'].get('pressure_kpa') is not None:
            self.p_atm_kpa = config['limits']['pressure_kpa']
        elif config['limits'].get('altitude_m') is not None:
            self.altitude_m = config['limits']['altitude_m']
            self.p_atm_kpa = pressure_by_altitude(self.altitude_m)

        # Dry bulb constant lines (vertical):
        if self.chart_params["with_constant_dry_temp"]:
            step = self.chart_params["constant_temp_step"]
            style = config['constant_dry_temp']
            temps_vl = f_range(self.dbt_min, self.dbt_max, step)
            heights = [1000 * humidity_ratio(
                saturation_pressure_water_vapor(t),
                p_atm_kpa=self.p_atm_kpa) for t in temps_vl]

            self.constant_dry_temp_data = PsychroCurves(
                [PsychroCurve([t, t], [self.w_min, h], style,
                              type_curve='constant_dry_temp_data',
                              label=None, logger=self._logger)
                 for t, h in zip(temps_vl, heights)],
                family_label=self.chart_params["constant_temp_label"])

        # Absolute humidity constant lines (horizontal):
        if self.chart_params["with_constant_humidity"]:
            step = self.chart_params["constant_humid_step"]
            style = config['constant_humidity']
            ws_hl = f_range(self.w_min + step, self.w_max + step / 10, step)
            dew_points = solve_curves_with_iteration(
                'DEW POINT', [x / 1000 for x in ws_hl],
                lambda x: dew_point_temperature(
                        water_vapor_pressure(
                            x, p_atm_kpa=self.p_atm_kpa)),
                lambda x: humidity_ratio(
                    saturation_pressure_water_vapor(x),
                    p_atm_kpa=self.p_atm_kpa))

            self.constant_humidity_data = PsychroCurves(
                [PsychroCurve([t_dp, self.dbt_max], [w, w], style,
                              type_curve='constant_humidity_data',
                              label=None, logger=self._logger)
                 for w, t_dp in zip(ws_hl, dew_points)],
                family_label=self.chart_params["constant_humid_label"])

        # Constant relative humidity curves:
        if self.chart_params["with_constant_rh"]:
            rh_perc_values = self.chart_params["constant_rh_curves"]
            rh_label_values = self.chart_params.get("constant_rh_labels", [])
            label_loc = self.chart_params.get("constant_rh_labels_loc", .85)
            style = config["constant_rh"]
            temps_ct_rh, curves_ct_rh = _gen_list_curves_range_temps(
                curve_constant_humidity_ratio,
                self.dbt_min, self.dbt_max, self.temp_step,
                rh_perc_values, p_atm_kpa=self.p_atm_kpa)

            self.constant_rh_data = PsychroCurves(
                [PsychroCurve(
                    temps_ct_rh, curve_ct_rh, style,
                    type_curve='constant_rh_data',
                    label_loc=label_loc, label='RH {:g} %'.format(rh)
                    if round(rh, 1) in rh_label_values else None,
                    logger=self._logger)
                    for rh, curve_ct_rh in zip(rh_perc_values, curves_ct_rh)],
                family_label=self.chart_params["constant_rh_label"])

        # Constant enthalpy lines:
        if self.chart_params["with_constant_h"]:
            step = self.chart_params["constant_h_step"]
            start, end = self.chart_params["range_h"]
            enthalpy_values = f_range(start, end, step)
            h_label_values = self.chart_params.get("constant_h_labels", [])
            label_loc = self.chart_params.get("constant_h_labels_loc", 1.)
            style = config["constant_h"]
            temps_max_constant_h = [
                dry_temperature_for_enthalpy_of_moist_air(
                    self.w_min / 1000, h)
                for h in enthalpy_values]

            sat_points = solve_curves_with_iteration(
                'ENTHALPHY', enthalpy_values,
                lambda x: dry_temperature_for_enthalpy_of_moist_air(
                    self.w_min / 1000 + 0.1, x),
                lambda x: enthalpy_moist_air(
                    x, saturation_pressure_water_vapor(x),
                    p_atm_kpa=self.p_atm_kpa))

            self.constant_h_data = PsychroCurves(
                [PsychroCurve(
                    [t_sat, t_max], [1000 * humidity_ratio(
                        saturation_pressure_water_vapor(t_sat),
                        self.p_atm_kpa), self.w_min], style,
                    type_curve='constant_h_data',
                    label_loc=label_loc, label='{:g} kJ/kg_da'.format(h)
                    if round(h, 3) in h_label_values else None,
                    logger=self._logger)
                    for t_sat, t_max, h in zip(
                    sat_points, temps_max_constant_h, enthalpy_values)],
                family_label=self.chart_params["constant_h_label"])

        # Constant specific volume lines:
        if self.chart_params["with_constant_v"]:
            step = self.chart_params["constant_v_step"]
            start, end = self.chart_params["range_vol_m3_kg"]
            vol_values = f_range(start, end, step)
            vol_label_values = self.chart_params.get("constant_v_labels", [])
            label_loc = self.chart_params.get("constant_v_labels_loc", 1.)
            style = config["constant_v"]
            temps_max_constant_v = [
                dry_temperature_for_specific_volume_of_moist_air(
                    0, specific_vol, p_atm_kpa=self.p_atm_kpa)
                for specific_vol in vol_values]
            sat_points = solve_curves_with_iteration(
                'CONSTANT VOLUME', vol_values,
                lambda x: dry_temperature_for_specific_volume_of_moist_air(
                    0, x, p_atm_kpa=self.p_atm_kpa),
                lambda x: specific_volume(
                    x, saturation_pressure_water_vapor(x),
                    p_atm_kpa=self.p_atm_kpa))

            self.constant_v_data = PsychroCurves(
                [PsychroCurve(
                    [t_sat, t_max], [1000 * humidity_ratio(
                        saturation_pressure_water_vapor(t_sat),
                        self.p_atm_kpa), 0],
                    style, type_curve='constant_v_data',
                    label_loc=label_loc, label='{:g} m3/kg_da'.format(vol)
                    if round(vol, 3) in vol_label_values else None,
                    logger=self._logger)
                    for t_sat, t_max, vol in zip(
                    sat_points, temps_max_constant_v, vol_values)],
                family_label=self.chart_params["constant_v_label"])

        # Constant wet bulb temperature lines:
        if self.chart_params["with_constant_wet_temp"]:
            step = self.chart_params["constant_wet_temp_step"]
            start, end = self.chart_params["range_wet_temp"]
            wbt_values = f_range(start, end, step)
            wbt_label_values = self.chart_params.get(
                "constant_wet_temp_labels", [])
            label_loc = self.chart_params.get(
                "constant_wet_temp_labels_loc", .05)
            style = config["constant_wet_temp"]
            w_max_constant_wbt = [humidity_ratio(
                saturation_pressure_water_vapor(wbt), self.p_atm_kpa)
                for wbt in wbt_values]

            self.constant_wbt_data = PsychroCurves(
                [PsychroCurve(
                    [wbt, self.dbt_max],
                    [1000 * w_max,
                     1000 * humidity_ratio(
                         saturation_pressure_water_vapor(self.dbt_max)
                         * relative_humidity_from_temps(
                             self.dbt_max, wbt, p_atm_kpa=self.p_atm_kpa),
                         p_atm_kpa=self.p_atm_kpa)], style,
                    type_curve='constant_wbt_data',
                    label_loc=label_loc, label='{:g} °C'.format(wbt)
                    if wbt in wbt_label_values else None, logger=self._logger)
                    for wbt, w_max in zip(wbt_values, w_max_constant_wbt)],
                family_label=self.chart_params["constant_wet_temp_label"])

        # Saturation line:
        if True:
            sat_style = config["saturation"]
            temps_sat_line, w_sat_line = _gen_list_curves_range_temps(
                curve_constant_humidity_ratio,
                self.dbt_min, self.dbt_max, self.temp_step, [100],
                p_atm_kpa=self.p_atm_kpa)

            self.saturation = PsychroCurves(
                [PsychroCurve(
                    temps_sat_line, w_sat_line[0], sat_style,
                    type_curve='saturation', logger=self._logger)])

        # Zones
        if self.chart_params["with_zones"] or zones_file is not None:
            self.append_zones(zones_file)