Skip to content

Latest commit

 

History

History
435 lines (266 loc) · 13.6 KB

06_farfield_polarisation.rst

File metadata and controls

435 lines (266 loc) · 13.6 KB
.. only:: html

    .. note::
        :class: sphx-glr-download-link-note

        Click :ref:`here <sphx_glr_download_auto_examples_06_farfield_polarisation.py>`
        to download the full example code

.. rst-class:: sphx-glr-example-title

Modelling Different Farfield Polarisations

This example uses the frequency domain :func:`lyceanem.models.frequency_domain.calculate_farfield` function to predict the farfield pattern for a linearly polarised aperture. This could represent an antenna array without any beamforming weights.

import numpy as np
import open3d as o3d
import copy

Setting Farfield Resolution and Wavelength

LyceanEM uses Elevation and Azimuth to record spherical coordinates, ranging from -180 to 180 degrees in azimuth, and from -90 to 90 degrees in elevation. In order to launch the aperture projection function, the resolution in both azimuth and elevation is requried. In order to ensure a fast example, 37 points have been used here for both, giving a total of 1369 farfield points.

The wavelength of interest is also an important variable for antenna array analysis, so we set it now for 10GHz, an X band aperture.

az_res = 37
elev_res = 37
wavelength = 3e8 / 10e9

Generating consistent point source to explore farfield polarisations, and rotating the source

from lyceanem.base_classes import points,structures,antenna_structures

aperture_coords=o3d.geometry.PointCloud()
point1=np.asarray([0.0,0,0]).reshape(1,3)
normal1=np.asarray([0,0,1.0]).reshape(1,3)
aperture_coords.points=o3d.utility.Vector3dVector(point1)
aperture_coords.normals=o3d.utility.Vector3dVector(normal1)
aperture=points([aperture_coords])
blockers=structures([None])
point_antenna=antenna_structures(blockers, aperture)


from lyceanem.models.frequency_domain import calculate_farfield

The first source polarisation is based upon the u-vector of the source point. When the excitation_function method of the antenna structure class is used, it will calculate the appropriate polarisation vectors based upon the local normal vectors.

desired_E_axis = np.zeros((1, 3), dtype=np.complex64)
desired_E_axis[0, 0] = 1.0
Etheta, Ephi = calculate_farfield(
    point_antenna.export_all_points(),
    point_antenna.export_all_structures(),
    point_antenna.excitation_function(desired_e_vector=desired_E_axis),
    az_range=np.linspace(-180, 180, az_res),
    el_range=np.linspace(-90, 90, elev_res),
    wavelength=wavelength,
    farfield_distance=20,
    elements=False,
    project_vectors=False,
)
.. rst-class:: sphx-glr-script-out

 Out:

 .. code-block:: none

    Structure does not exist
    no structures
    /home/timtitan/anaconda3/envs/EMDevelopment/lib/python3.8/site-packages/numba/cuda/compiler.py:726: NumbaPerformanceWarning: Grid size (6) < 2 * SM count (28) will likely result in GPU under utilization due to low occupancy.
      warn(NumbaPerformanceWarning(msg))
    /home/timtitan/anaconda3/envs/EMDevelopment/lib/python3.8/site-packages/numba/cuda/compiler.py:726: NumbaPerformanceWarning: Grid size (6) < 2 * SM count (28) will likely result in GPU under utilization due to low occupancy.
      warn(NumbaPerformanceWarning(msg))
    /home/timtitan/anaconda3/envs/EMDevelopment/lib/python3.8/site-packages/numba/cuda/cudadrv/devicearray.py:885: NumbaPerformanceWarning: Host array used in CUDA kernel will incur copy overhead to/from device.
      warn(NumbaPerformanceWarning(msg))




Antenna Pattern class is used to manipulate and record antenna patterns

from lyceanem.base_classes import antenna_pattern

u_pattern = antenna_pattern(
    azimuth_resolution=az_res, elevation_resolution=elev_res
)
u_pattern.pattern[:, :, 0] = Etheta
u_pattern.pattern[:, :, 1] = Ephi
u_pattern.display_pattern(desired_pattern='Power')
.. image-sg:: /auto_examples/images/sphx_glr_06_farfield_polarisation_001.png
   :alt: Power Pattern
   :srcset: /auto_examples/images/sphx_glr_06_farfield_polarisation_001.png
   :class: sphx-glr-single-img





The second source polarisation is based upon the v-vector of the source point.

desired_E_axis = np.zeros((1, 3), dtype=np.complex64)
desired_E_axis[0, 1] = 1.0
Etheta, Ephi = calculate_farfield(
    point_antenna.export_all_points(),
    point_antenna.export_all_structures(),
    point_antenna.excitation_function(desired_e_vector=desired_E_axis),
    az_range=np.linspace(-180, 180, az_res),
    el_range=np.linspace(-90, 90, elev_res),
    wavelength=wavelength,
    farfield_distance=20,
    elements=False,
    project_vectors=False,
)


v_pattern = antenna_pattern(
    azimuth_resolution=az_res, elevation_resolution=elev_res
)
v_pattern.pattern[:, :, 0] = Etheta
v_pattern.pattern[:, :, 1] = Ephi
v_pattern.display_pattern(desired_pattern='Power')
.. image-sg:: /auto_examples/images/sphx_glr_06_farfield_polarisation_002.png
   :alt: Power Pattern
   :srcset: /auto_examples/images/sphx_glr_06_farfield_polarisation_002.png
   :class: sphx-glr-single-img


.. rst-class:: sphx-glr-script-out

 Out:

 .. code-block:: none

    Structure does not exist
    no structures
    /home/timtitan/anaconda3/envs/EMDevelopment/lib/python3.8/site-packages/numba/cuda/compiler.py:726: NumbaPerformanceWarning: Grid size (6) < 2 * SM count (28) will likely result in GPU under utilization due to low occupancy.
      warn(NumbaPerformanceWarning(msg))
    /home/timtitan/anaconda3/envs/EMDevelopment/lib/python3.8/site-packages/numba/cuda/cudadrv/devicearray.py:885: NumbaPerformanceWarning: Host array used in CUDA kernel will incur copy overhead to/from device.
      warn(NumbaPerformanceWarning(msg))
    /home/timtitan/Documents/10-19-Research-Projects/14-Electromagnetics-Modelling/14.04-Python-Development/LyceanEM/lyceanem/electromagnetics/beamforming.py:1083: RuntimeWarning: divide by zero encountered in log10
      logdata = 20 * np.log10(data)




The third source polarisation is based upon the n-vector of the source point. Aligned with the source point normal.

desired_E_axis = np.zeros((1, 3), dtype=np.complex64)
desired_E_axis[0, 2] = 1.0
Etheta, Ephi = calculate_farfield(
    point_antenna.export_all_points(),
    point_antenna.export_all_structures(),
    point_antenna.excitation_function(desired_e_vector=desired_E_axis),
    az_range=np.linspace(-180, 180, az_res),
    el_range=np.linspace(-90, 90, elev_res),
    wavelength=wavelength,
    farfield_distance=20,
    elements=False,
    project_vectors=False,
)

n_pattern = antenna_pattern(
    azimuth_resolution=az_res, elevation_resolution=elev_res
)
n_pattern.pattern[:, :, 0] = Etheta
n_pattern.pattern[:, :, 1] = Ephi
n_pattern.display_pattern(desired_pattern='Power')
.. image-sg:: /auto_examples/images/sphx_glr_06_farfield_polarisation_003.png
   :alt: Power Pattern
   :srcset: /auto_examples/images/sphx_glr_06_farfield_polarisation_003.png
   :class: sphx-glr-single-img


.. rst-class:: sphx-glr-script-out

 Out:

 .. code-block:: none

    Structure does not exist
    no structures
    /home/timtitan/anaconda3/envs/EMDevelopment/lib/python3.8/site-packages/numba/cuda/compiler.py:726: NumbaPerformanceWarning: Grid size (6) < 2 * SM count (28) will likely result in GPU under utilization due to low occupancy.
      warn(NumbaPerformanceWarning(msg))
    /home/timtitan/anaconda3/envs/EMDevelopment/lib/python3.8/site-packages/numba/cuda/cudadrv/devicearray.py:885: NumbaPerformanceWarning: Host array used in CUDA kernel will incur copy overhead to/from device.
      warn(NumbaPerformanceWarning(msg))




The point source can then be rotated, by providing a rotation matrix, and the u,v,n directions are moved with it in a consistent way.

point_antenna.rotate_antenna(o3d.geometry.get_rotation_matrix_from_axis_angle(np.radians(np.asarray([90.0,0.0,0.0]))))

desired_E_axis = np.zeros((1, 3), dtype=np.complex64)
desired_E_axis[0, 0] = 1.0
Etheta, Ephi = calculate_farfield(
    point_antenna.export_all_points(),
    point_antenna.export_all_structures(),
    point_antenna.excitation_function(desired_e_vector=desired_E_axis),
    az_range=np.linspace(-180, 180, az_res),
    el_range=np.linspace(-90, 90, elev_res),
    wavelength=wavelength,
    farfield_distance=20,
    elements=False,
    project_vectors=False,
)
u_pattern.pattern[:, :, 0] = Etheta
u_pattern.pattern[:, :, 1] = Ephi
u_pattern.display_pattern(desired_pattern='Power')


desired_E_axis = np.zeros((1, 3), dtype=np.complex64)
desired_E_axis[0, 1] = 1.0
Etheta, Ephi = calculate_farfield(
    point_antenna.export_all_points(),
    point_antenna.export_all_structures(),
    point_antenna.excitation_function(desired_e_vector=desired_E_axis),
    az_range=np.linspace(-180, 180, az_res),
    el_range=np.linspace(-90, 90, elev_res),
    wavelength=wavelength,
    farfield_distance=20,
    elements=False,
    project_vectors=False,
)
v_pattern.pattern[:, :, 0] = Etheta
v_pattern.pattern[:, :, 1] = Ephi
v_pattern.display_pattern(desired_pattern='Power')


desired_E_axis = np.zeros((1, 3), dtype=np.complex64)
desired_E_axis[0, 2] = 1.0
Etheta, Ephi = calculate_farfield(
    point_antenna.export_all_points(),
    point_antenna.export_all_structures(),
    point_antenna.excitation_function(desired_e_vector=desired_E_axis),
    az_range=np.linspace(-180, 180, az_res),
    el_range=np.linspace(-90, 90, elev_res),
    wavelength=wavelength,
    farfield_distance=20,
    elements=False,
    project_vectors=False,
)
n_pattern.pattern[:, :, 0] = Etheta
n_pattern.pattern[:, :, 1] = Ephi
n_pattern.display_pattern(desired_pattern='Power')
.. rst-class:: sphx-glr-horizontal


    *

      .. image-sg:: /auto_examples/images/sphx_glr_06_farfield_polarisation_004.png
         :alt: Power Pattern
         :srcset: /auto_examples/images/sphx_glr_06_farfield_polarisation_004.png
         :class: sphx-glr-multi-img

    *

      .. image-sg:: /auto_examples/images/sphx_glr_06_farfield_polarisation_005.png
         :alt: Power Pattern
         :srcset: /auto_examples/images/sphx_glr_06_farfield_polarisation_005.png
         :class: sphx-glr-multi-img

    *

      .. image-sg:: /auto_examples/images/sphx_glr_06_farfield_polarisation_006.png
         :alt: Power Pattern
         :srcset: /auto_examples/images/sphx_glr_06_farfield_polarisation_006.png
         :class: sphx-glr-multi-img


.. rst-class:: sphx-glr-script-out

 Out:

 .. code-block:: none

    Structure does not exist
    no structures
    /home/timtitan/anaconda3/envs/EMDevelopment/lib/python3.8/site-packages/numba/cuda/compiler.py:726: NumbaPerformanceWarning: Grid size (6) < 2 * SM count (28) will likely result in GPU under utilization due to low occupancy.
      warn(NumbaPerformanceWarning(msg))
    /home/timtitan/anaconda3/envs/EMDevelopment/lib/python3.8/site-packages/numba/cuda/cudadrv/devicearray.py:885: NumbaPerformanceWarning: Host array used in CUDA kernel will incur copy overhead to/from device.
      warn(NumbaPerformanceWarning(msg))
    /home/timtitan/Documents/10-19-Research-Projects/14-Electromagnetics-Modelling/14.04-Python-Development/LyceanEM/lyceanem/electromagnetics/beamforming.py:1083: RuntimeWarning: divide by zero encountered in log10
      logdata = 20 * np.log10(data)
    Structure does not exist
    no structures
    Structure does not exist
    no structures





.. rst-class:: sphx-glr-timing

   **Total running time of the script:** ( 0 minutes  28.870 seconds)


.. only :: html

 .. container:: sphx-glr-footer
    :class: sphx-glr-footer-example



  .. container:: sphx-glr-download sphx-glr-download-python

     :download:`Download Python source code: 06_farfield_polarisation.py <06_farfield_polarisation.py>`



  .. container:: sphx-glr-download sphx-glr-download-jupyter

     :download:`Download Jupyter notebook: 06_farfield_polarisation.ipynb <06_farfield_polarisation.ipynb>`


.. only:: html

 .. rst-class:: sphx-glr-signature

    `Gallery generated by Sphinx-Gallery <https://sphinx-gallery.github.io>`_