{ "cells": [ { "cell_type": "markdown", "id": "6793a422-43f2-4c6d-977f-0fc718779005", "metadata": {}, "source": [ "# Theory" ] }, { "cell_type": "markdown", "id": "05a95ca9-4213-4976-8970-9927274b2d2e", "metadata": {}, "source": [ "Irradiance of direct light on a plane depends on angle of incidence,\n", "$$\n", "\\begin{align}\n", "&N & \\textrm{direct normal irradiance} \\\\\n", "&\\theta_{i} & \\textrm{incidence angle} \\\\\n", "&\\theta_{zenith} & \\textrm{zenith angle, incidence angle when instrument horizontal} \\\\\n", "\\mu_i &= \\cos(\\theta_{i}) & \\textrm{projection factor} \\\\\n", "\\mu_0 &= \\cos(\\theta_{zenith}) & \\textrm{projection factor for hozizontal instrument} \\\\\n", "\\mu_t & = \\cos(\\theta_{zenith}, \\textrm{pitch, roll, heading}) & \\textrm{projection factor of tilted platform}\\\\\n", "I(\\mu_i) &= N \\mu_i & \\textrm{observed direct irradiance} \\\\\n", "I(\\mu_i) = N \\mu_i &\\neq N \\mu_0 = I(\\mu_0), & \\text{for } \\mu_i \\neq \\mu_0 \n", "\\end{align}\n", "$$\n", "where $I$ is the irradiance at the incidence angle $\\theta_i$ and $N$ is the direct normal irradiance. Often the projection factor $\\mu_i$ is used rather then the incidence angle. When the instrument is horizontal $\\theta_i$ is equal to the solar thenith angle and the projection factor is $\\mu_0$\n", "\n", "$$\n", "\\begin{align}\n", "\\end{align}\n", "$$\n", "\n", "Irradiance of diffuse radiation is less effected by the tilt, but gets very complicated when treated precisly.\n", "Here we assume the simmples approximation --> The diffuse radiation is isotropic --> diffuse is not effected by tilt. Even this apprimation breaks down the more ground comes into few with increasing tilt." ] }, { "cell_type": "markdown", "id": "bc580751-d73f-464f-97e5-18ba5e36e6d1", "metadata": {}, "source": [ "![Tilt illustration](tilt_illustration.png)" ] }, { "cell_type": "markdown", "id": "1e5e49f2-ae3c-4846-8a7a-79920ae6ae6e", "metadata": {}, "source": [ "## Solving the linear equations getting tilt corrected direct and global" ] }, { "cell_type": "code", "execution_count": 13, "id": "bf2a4809-a33a-4a0f-9bee-116fc1b30769", "metadata": {}, "outputs": [], "source": [ "import sympy as sp" ] }, { "cell_type": "markdown", "id": "cb43a625-8e27-41e0-8be1-9497adc08e9a", "metadata": {}, "source": [ "$$\n", "\\begin{aligned}\n", "&D & \\textrm{diffuse irradiance} \\\\\n", "G_t &= N\\mu_t + D & \\textrm{global irradiance of tilted plattform}\\\\ \n", "G_0 &= N\\mu_0 + D & \\textrm{global horizontal irradiance} \\\\\n", "f_D &= \\frac{D}{G_t} &\\textrm{diffuse fraction of titlted global irradiance}\n", "\\end{aligned}\n", "$$\n", "\n", "Solving the equation system for the unknowns $G_0$, $N$, and $D$, in terms of the remaining variables $G_t$, $\\mu_t$, $\\mu_0$, and $f_D$, yields\n", "\n", "$$\n", "\\begin{aligned}\n", "G_0 &= G_t~\\frac{-\\mathrm{f_D}~\\mu_0 + \\mathrm{f_D}~\\mu_t + \\mu_0}{\\mu_t}\\\\\n", "N &= G_t~\\frac{1 -\\mathrm{f_D}}{\\mu_t} \\\\\n", "D &= G_t~\\mathrm{f_D}\n", "\\end{aligned}\n", "$$" ] }, { "cell_type": "code", "execution_count": 14, "id": "37dd2487-5e05-4146-9e20-3c9582cdee16", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "[{Diff: Gt*ddt,\n", " G0: (-Gt*ddt*mu0 + Gt*ddt*mut + Gt*mu0)/mut,\n", " N: (-Gt*ddt + Gt)/mut}]" ] }, "execution_count": 14, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# based on the ratio of diffuse and global. This is preferable as it uses two measurments that are actually observed\n", "Gt, N, mut, mu0, Diff, G0, ddt = sp.symbols(\"Gt N mut mu0 Diff G0 ddt\") \n", "\n", "#equations\n", "eqs = [sp.Eq(Gt, N * mut + Diff), \n", " sp.Eq(G0, N * mu0 + Diff), \n", " sp.Eq(ddt, Diff/Gt), ] \n", "sol = sp.solve(eqs, [G0, N,Diff], dict=True)\n", "sol" ] }, { "cell_type": "markdown", "id": "edbf155d-628b-4b0f-bc7d-7c4e046844d9", "metadata": {}, "source": [ "# Usage" ] }, { "cell_type": "markdown", "id": "fb886b67-0a9a-4d29-a6a3-96c3432206d0", "metadata": {}, "source": [ "1. Ensure you have an xarray dataset ds with the required variables and units (let you be guided by error messages).\n", "2. Apply installation offsets for roll and pitch or determine with find_offsets function in tiltcorrection module.\n", "3. Create a CombinedGlobalDiffuseDirect instance (or just global ... this might not be implemented yet)\n", "4. Call the apply_tilt_correction method. the output is a new CombinedGlobalDiffuseDirect instance with tiltcorrection applied. " ] }, { "cell_type": "code", "execution_count": null, "id": "330ae683-4fc6-4207-86ec-ea5314a055fc", "metadata": {}, "outputs": [], "source": [ "rin = atmbsr.CombinedGlobalDiffuseDirect(ds, verbose = True)\n", "out = rin.apply_tilt_correction(sensor_response_time=rs)" ] }, { "cell_type": "markdown", "id": "dbf35d46-4e14-4f84-a7a9-a09986b15703", "metadata": {}, "source": [ "# sun incidence angel playground" ] }, { "cell_type": "code", "execution_count": 1, "id": "a1529cfc-a6a2-4a85-af89-73de693d1373", "metadata": {}, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ "/Users/htelg/prog/atm-py/atmPy/radiation/retrievals/tiltcorrection.py:83: SyntaxWarning: invalid escape sequence '\\m'\n", " $N$ the direct normal component, $\\mathrm{Diff}$ the diffuse component, $\\mu_t$ the\n" ] } ], "source": [ "import atmPy.radiation.retrievals.tiltcorrection as atmtilt" ] }, { "cell_type": "code", "execution_count": 4, "id": "fda74d88-55ff-451e-b1c9-7b505eeb278f", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "np.float64(20.999999999999986)" ] }, "execution_count": 4, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# plain flys in the sun and tilts nose up -> zenith angle gets larger\n", "out = atmtilt.solar_incidence_angle(zenith = np.deg2rad(20), \n", " azimuth = np.deg2rad(90), \n", " pitch = np.deg2rad(1),\n", " roll = np.deg2rad(0),\n", " heading = np.deg2rad(90))\n", "np.rad2deg(out)" ] }, { "cell_type": "code", "execution_count": 9, "id": "b4b73336-0903-4137-a867-ffb8a0dec04f", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "np.float64(18.999999999999975)" ] }, "execution_count": 9, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# opposite heading\n", "out = atmtilt.solar_incidence_angle(zenith = np.deg2rad(20), \n", " azimuth = np.deg2rad(90), \n", " pitch = np.deg2rad(1),\n", " roll = np.deg2rad(0),\n", " heading = np.deg2rad(90+180))\n", "np.rad2deg(out)" ] }, { "cell_type": "code", "execution_count": 8, "id": "7ceb24d3-4d27-4d52-8051-aacc5020ec29", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "np.float64(18.999999999999975)" ] }, "execution_count": 8, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# plain flys in the paralel to the sun and rols right side down (positive roll) -> zenith angle gets smaller\n", "out = atmtilt.solar_incidence_angle(zenith = np.deg2rad(20), \n", " azimuth = np.deg2rad(180), \n", " pitch = np.deg2rad(0),\n", " roll = np.deg2rad(1),\n", " heading = np.deg2rad(90))\n", "np.rad2deg(out)" ] }, { "cell_type": "code", "execution_count": 10, "id": "90addbe5-961f-4093-b6b9-4c57f7564b6a", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "np.float64(20.999999999999986)" ] }, "execution_count": 10, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# oposite heading\n", "out = atmtilt.solar_incidence_angle(zenith = np.deg2rad(20), \n", " azimuth = np.deg2rad(180), \n", " pitch = np.deg2rad(0),\n", " roll = np.deg2rad(1),\n", " heading = np.deg2rad(90+180))\n", "np.rad2deg(out)" ] }, { "cell_type": "code", "execution_count": 11, "id": "01cab9fc-92a3-4017-acb9-692a34156c78", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "np.float64(20.023961889117096)" ] }, "execution_count": 11, "metadata": {}, "output_type": "execute_result" } ], "source": [] } ], "metadata": { "kernelspec": { "display_name": "py13", "language": "python", "name": "py13" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.13.13" } }, "nbformat": 4, "nbformat_minor": 5 }