# Copyright 2023 Alireza Aghamohammadi
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
# http://www.apache.org/licenses/LICENSE-2.0
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import math
from .model import HottelModel
from .observer import Observer
[docs]
class AtmosphericTransmission:
r"""
A class to model the atmospheric transmission.
"""
def __init__(
self,
climate_type: str,
observer_altitude: int,
observer_latitude: float,
):
r"""
To instantiate the ``AtmosphericTransmission`` class,
provide the following three parameters.
:param climate_type: The type of climate.
:type climate_type: str
:param observer_altitude: The altitude of the observer in meters.
:type observer_altitude: int
:param observer_latitude: The latitude of the observer in degrees.
:type observer_latitude: float
"""
self.hottel_model = HottelModel()
(
self.a0,
self.a1,
self.k,
) = self.hottel_model.calculate_transmittance_components(
climate_type, observer_altitude
)
self.observer = Observer(observer_latitude)
[docs]
def calculate_transmittance(self, day_of_year: int, solar_time: float) -> float:
r"""
Calculate the effective atmospheric transmission coefficient of the direct beam.
The effective atmospheric transmission coefficient of the direct beam
is calculated using the formula:
.. math::
\tau_b = a_0 + a_1 \times \exp\left(-\frac{k}{\cos(\theta_z)}\right)
| - :math:`\tau_b` is the effective atmospheric transmission
coefficient of the direct beam
| - :math:`a_0`, :math:`a_1`, and :math:`k` are the components
of clear-sky beam radiation transmittance
| - :math:`\theta_z` is the solar zenith angle
:param day_of_year: The day of the year.
:type day_of_year: int
:param solar_time: The solar time in seconds.
:type solar_time: float
:return: The effective atmospheric transmission coefficient of the direct beam.
:rtype: float
"""
zenith_angle = self.observer.calculate_zenith_angle(day_of_year, solar_time)
cos_zenith_angle = math.cos(zenith_angle)
EPSILON = 1e-8 # Small constant to prevent division by zero
if abs(cos_zenith_angle) < EPSILON:
return self.a0
else:
return self.a0 + self.a1 * math.exp(-self.k / cos_zenith_angle)