Metadata-Version: 1.1
Name: antenna-optimizer
Version: 0.2
Summary: Optimize antennas using NEC and a genetic algorithm
Home-page: https://github.com/schlatterbeck/antenna-optimizer
Author: Ralf Schlatterbeck
Author-email: rsc@runtux.com
License: BSD License
Description: Antenna Optimizer
        =================
        
        .. |ohm| unicode:: U+02126 .. Omega
        .. |_| unicode:: U+00A0 .. Non-breaking space
           :trim:
        
        This project can optimize anntennas using genetic algorithms.  It uses
        my pgapy_ Python wrapper for PGApack_, the parallel genetic algorithm
        library, originally by David Levine at Argonne National Laboratory and
        currently maintained by me. It also uses PyNEC_, the Python wrapper for
        NEC2++, the C++ version of the `Numerical Electromagnetics Code`_.
        
        Originally this started out with a low-gain two-element antenna where
        the driven element is a folded dipole. One of the requirements for that
        antenna was that it should have 50 |_| |ohm| impedance and at least some
        forward gain. Optimizing this antenna by hand soon turned out to be
        tedious and I started experimenting with optimization by a genetic
        algorithm.
        
        You can find the original experiments in ``folded.nec`` and
        ``folded2.nec``. These are input files to the command-line NEC programs.
        You can either use the ``nec2c`` command-line program which produces an
        output file that can be viewed with ``xnecview`` or you can use
        graphical ``xnec2c`` program. All run under Linux and are included in
        the Debian Linux distribution. The ``.nec`` files *may* also be usable
        with other NEC versions on other operating systems but I have not tried.
        
        For optimizing the two-element Yagi-Uda you can use the command-line
        tool ``folded_antenna`` where the optimizer is implemented in
        ``folded.py``. Later a 3-element antenna with the same principles was
        added in ``folded_3ele.py`` callable with the command-line tool
        ``folded_3ele_antenna``.
        
        The ``antenna_model.py`` factors out the common parts of the various
        antennas.
        
        The ``hb9cv.py`` with the command-line tool ``hb9cv_antenna`` models the
        well-know HB9CV antenna but only very crudely. NEC2 isn't really suited
        for modelling the phasing stubs of that antenna because it doesn't like
        parallel wires that are too close. I mainly did this for comparing some
        of the antennas resulting from optimization with the well-known
        performance of the HB9CV.
        
        In the file ``logper.py`` with the command-line tool ``logper_antenna``
        you can find a 9-element log-periodic antenna.  It can currently not be
        optimized, the performance of the real antenna is better than the
        results obtained with NEC, so I didn't implement an optimizer for it
        yet.
        
        All the antenna programs take an action as mandatory argument. The
        action is typically either ``optimize`` for running the optimizer or
        ``necout`` for creating a ``.nec`` file which can then be fed to one of
        the nec programs mentioned above. When running the optimizer it makes
        sense to experiment with different random seeds, each random seed will
        usually produce a different antenna. In addition there are some
        experimental actions, ``frgain`` prints the forward and backward gains
        (in dBi) for the lowest, the middle, and the highest frequencies and the
        VSWR for those. The ``gain`` action visualizes the 3D antenna gain
        pattern and the ``swr`` action visualizes the VSWR over the given
        frequency range. Note that both, the ``gain`` and the ``swr`` action
        compute the antenna data over the whole frequency range using NEC and
        that may take some time.
        
        The output of the optimizer is text (usually redirected to a file) that
        prints the evaluation, the VSWR, maximum gain, and forward/backward
        ratio of the best antenna for every 10th generation of the genetic
        algorithm. In addition the command-line options to create that antenna
        are printed. When the genetic algorithm doesn't make any more progress,
        the search terminates and the data of the best evaluation are given. An
        example of the last lines of such a text is as follows. The data is from
        one of the best 2-element antennas was obtained with the random seed 26
        of an earlier version of the program::
        
            The Best Evaluation: 2.886437e+02.
            The Best String:
            -r 0.0364 -d 0.0444 -l 0.1704 -4 0.1075
            VSWR: [1.7901433511443068, 1.1495780609982815, 1.7995760521232753]
            GMAX: 6.69913175227, RMAX: -3.03663376703
            Cache hits: 5670/9243 61.34%
            Eval: 288.64
            [ 101011001100101001111000000010011 ]
        
        This tells us the evaluation (which is meaningful only to the
        genetic algorithm), the genetic algorithm *maximizes* this value.
        The command-line options after the line ``The Best String:`` can be used
        to create a ``.nec`` file for that antenna. The antenna in the example
        has a voltage standing wave ratio of < |_| 1.8 at the band ends and
        around 1.15 in the middle of the band (the 70cm band from 430 to
        440 |_| MHz in that case). The forward gain (in the middle of the band)
        is 6.7 |_| dBi. The RMAX value is the (maximum) backward gain (in a 30
        degree area in the back). So the F/B ratio of that antenna is::
        
         6.7 dB - -3.0 dB = 9.7 dB
        
        The last line of the text output contains the genetic representation of
        that antenna.
        The ``.nec`` file for the antenna above which was optimized with an early
        version of this package can be created with the command::
        
         folded_antenna -r 0.0364 -d 0.0444 -l 0.1704 -4 0.1075 necout > folded-opt.nec
        
        The command-line options specify the radius of the folded dipole, the
        distance of the reflector from the folded dipole, the (half) length of
        the reflector, and the (half) length of the straight part of the folded
        dipole, respectively.
        
        According to NEC it has a standing wave ratio (VSWR) of < |_| 1.8 from
        430-440 |_| MHz, a forward gain of > |_| 6.5 dBi over the whole
        frequency range and a Forward/Back Ratio of 8-11 dB.
        
        If you want to implement an optimizer for your own antenna, look at the
        file ``folded.py``: You need to implement a class that defines the
        geometry of the new antenna and an optimizer class that initializes the
        gene ranges and implements a ``compute_antenna`` method that returns an
        instance of your antenna class with the parameters obtained from the
        given gene. All lengths in the models are metric (in meters) as is the
        default in NEC.
        
        A recent addition to this package involves modelling of coax cables.
        This uses information from an old article by Frank Witt [1]_ to derive
        everything necessary to model a transmission line *with* loss from the
        manufacturer cable data. The command-line tool for using these coax
        models is named ``coaxmodel``. Again this command has several
        sub-commands: 
        
        - ``loss``: This displays the fitted loss-curves from the manufacturer
          data against the curve-fit algorithm used, you can see how much
          difference in dB the fitted curve has to the loss at certain
          frequencies given by the manufacturer data.
        - ``match`` computes the impedance at the load and input (depending on
          which was given as an input the other is computed), the matched and
          total loss (the matched loss is the loss in the cable if the load is
          prefectly matched, the total loss is the sum of the matched loss and
          the additional loss due to reflections), the SWR and data for various
          stub-matches to get to the cable impedance Z0.
        - ``resonator`` computes the resistance and Q-factor of a coax resonator
          at the given frequency. A resonator is a piece of cable that either
          has a short-circuit or an open-circuit at the far end. The sub-command
          computes resonators for quarter and half wave at the given frequency.
        - ``stub`` computes the length, Q-factor, and resulting impedance as
          well as the inductance or capacitance of a stub for a given impedance
          and frequency. The impedance by default is -100j Ohm and can be
          changed with the -x option. The stub with the shortest resulting
          length is chosen, so for a negative reactance an open stub is chosen
          while for a positive reactance a closed stub is chosen.
        
        For all these sub-commands you can specify the frequency, length of
        cable and impedance (either at the load or at the end of the cable) to
        be used in computing the results. You can specify complex impedances as
        a python complex number in the format a+bj, e.g. 50-500j.
        
        Finally the ``transmission_line`` program can optimize the stub-matching
        for a transmission line using NEC. By default a lossless line is asumed.
        Also by default a closed stub at the closest possible position is
        searched.
        
        Transmission lines can be modelled by NEC with the ``TL`` (transmission
        line) card.  But NEC can also model arbitrary (symmetric, passive)
        networks with the ``NT`` (network) card. We use this (and the code in
        ``coaxmodel.py``) to model a real cable *with loss* for stub matching.
        It is instructive to compare the values for stub-matching obtained
        analytically from ``coaxmodel`` with the values obtained from an
        optimization with the genetic algorithm by ``transmission_line``. Note
        that the coaxmodel takes frequecies in Hz while transmission_line (which
        uses NEC) accepts frequencies in MHz. So we match a complex impedance of
        75+15j |Ohm| for example::
        
         coaxmodel -c sytronic_RG_58_CU -f 435e6 -z 75+15j match
        
        This yields a stub of length 8.007 cm attached 7.888 cm from the load when
        matching with a closed stub. When optimizing with ``transmission_line``::
        
         transmission_line -c sytronic_RG_58_CU -f 435 -z 75+15j optimize
        
        we get 8.016cm for the stub length and 7.6cm for the distance of the
        stub from the load. We can visualize this over a given frequency range
        by either producing NEC output::
        
         transmission_line -c sytronic_RG_58_CU -f 435 -z 75+15j -i 50 \
            -l 0.0816 -d 0.076 --frqstart=430 --frqend=440 necout > x1.nec
         transmission_line -c sytronic_RG_58_CU -f 435 -z 75+15j -i 50 \
            -l 0.08007 -d 0.07888 --frqstart=430 --frqend=440 necout > x2.nec
        
        And the compute the nec model and display with::
        
         nec2c -i x1.nec > x1.out
         nec2c -i x2.nec > x2.out
         xnecview x1.out
         xnecview x2.out
        
        Or directly display the VSWR curves with::
        
         transmission_line -c sytronic_RG_58_CU -f 435 -z 75+15j -i 50 \
            -l 0.0816 -d 0.076 --frqstart=430 --frqend=440 swr
         transmission_line -c sytronic_RG_58_CU -f 435 -z 75+15j -i 50 \
            -l 0.08007 -d 0.07888 --frqstart=430 --frqend=440 swr
        
        Both are close enough, the SWR is below 1.1 over the whole frequency
        range given. Note that this can change drastically if load impedances
        with a higher VSWR are matched.
        
        Also note that the NEC files produced in the example above have a different
        NEC network *for each frequency*. This is because NEC models networks
        using an `admittance matrix`_ which is frequency dependent.
        
        This means the sequence of two ``NT``
        cards, a ``TL`` card, a ``FR`` card and a ``RP`` card are repeated for
        each frequency. Here the two ``NT`` cards define the network of the
        cable from the load to the stub and the stub itself while the ``TL``
        card defines the length of a lossless transmission line from the stub to
        the source. The ``FR`` card specifies a single frequency and the ``RP``
        card defines a radiation pattern and triggers computation. This format
        is perfectly valid NEC code, but certain programs (like the popular
        ``xnec2c``) cannot deal with this format and display only a single
        frequency.
        
        .. [1] Frank Witt. Transmission line properties from manufacturer’s
           data. In R. Dean Straw, editor, The ARRL Antenna Compendium, volume 6,
           pages 179–183. American Radio Relay League (ARRL), 1999.
        
        .. _pgapy:  https://pypi.org/project/PGAPy/
        .. _PGApack: https://github.com/schlatterbeck/pgapack
        .. _PyNEC: https://pypi.org/project/PyNEC/
        .. _`PyNEC source`: https://github.com/tmolteno/python-necpp
        .. _`Numerical Electromagnetics Code`:
            https://en.wikipedia.org/wiki/Numerical_Electromagnetics_Code
        .. _`admittance matrix`: https://en.wikipedia.org/wiki/Admittance_parameters
        
        Changes
        -------
        
        Version 0.2: More cable data
        
        - Fix setup to correctly specify dependencies
        - Add more cable data the following command will list supported cable
          types::
        
            coaxmodel --help
        
        Version 0.1: Initial Release
        
Platform: Any
Classifier: Development Status :: 5 - Production/Stable
Classifier: License :: OSI Approved :: BSD License
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python
Classifier: Intended Audience :: Developers
Classifier: Programming Language :: Python :: 2
Classifier: Programming Language :: Python :: 2.7
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.5
Classifier: Programming Language :: Python :: 3.6
Classifier: Programming Language :: Python :: 3.7
Classifier: Programming Language :: Python :: 3.8
Classifier: Programming Language :: Python :: 3.9
