__init__.py
analyser.py
   vswr(model, Z0 = 50):
Return the antenna VSWR at the feed point assuming a 50 ohm system
Or another value if specified
   get_gains_at_gain_point(model):
   plot_pattern_gains(model, azimuth_deg = None, elevation_deg = None, components = ['vert_gain_dBi', 'horiz_gain_dBi'], gain_scale_max = 0, gain_scale_range_dB = 30):
Read the radiation pattern into a Python dictionary:
'azimuth_deg': float,
'elevation_deg': float,
'vert_gain_dBi': float,
'horiz_gain_dBi': float,
'total_gain_dBi': float,
'axial_ratio_dB': float,
'tilt_deg': float,
'sense': string,
'E_theta_mag': float,
'E_theta_phase_deg': float,
'E_phi_mag': float,
'E_phi_phase_deg': float
modeller.py
class NECModel:
   set_name(name):
Set the name of the model. This is used in NEC input file generation and is reflected in the NEC
output file name. It is permissible to use this function to re-set the name after a NEC run has completed,
so that the analysis continues (with updated input parameters) and outputs more than one test case
   set_wire_conductivity(sigma):
Set wire conductivity to be assumed for all wires that don't have an explicitly-set load.
   set_frequency(MHz):
Request NEC to perform all analysis at the specified frequency.
   set_gain_point(azimuth_deg, elevation_deg):
Set the azimuth and elevation of a single gain point that
must appear in the output radiation pattern
   set_angular_resolution(az_step_deg, el_step_deg):
Set resolution required in az and el in degrees
If a ground is specified, NEC will be asked for a hemisphere, otherwise a sphere
   set_ground(eps_r, sigma, **origin_height):
Sets the ground relative permitivity and conductivity. Currently limited to simple choices.
If eps_r = 1, nec is told to use no ground (free space model), and you may omit the origin height parameter
If you don't call this function, free space will be assumed.
Othewise you should set the origin height so that the antenna reference point X,Y,Z = (0,0,0) is set to be
the specified distance above ground.
Parameters:
eps_r (float): relative permittivity (relative dielectric constant) of the ground
sigma (float): conductivity of the ground in mhos/meter
origin_height_{units_string} (float): Height of antenna reference point X,Y,Z = (0,0,0)
   place_RLC_load(geomObj, R_Ohms, L_uH, C_pf, load_type = 'series', load_alpha_object=-1, load_wire_index=-1, load_alpha_wire=-1):
inserts a single segment containing an RLC load into an existing geometry object
Position within the object is specied as
EITHER:
load_alpha_object (range 0 to 1) as a parameter specifying the length of
wire traversed to reach the item by following each wire in the object,
divided by the length of all wires in the object
(This is intended to be used for objects like circular loops where there
are many short wires each of the same length)
OR:
load_wire_index AND load_alpha_wire
which specify the i'th wire (0 to n-1) in the n wires in the object, and the distance along that
wire divided by that wire's length
NEC LD card specification: https://www.nec2.org/part_3/cards/ld.html
   place_feed( geomObj, feed_alpha_object=-1, feed_wire_index=-1, feed_alpha_wire=-1):
Inserts a single segment containing the excitation point into an existing geometry object.
Position within the object is specied as
EITHER:
feed_alpha_object (range 0 to 1) as a parameter specifying the length of
wire traversed to reach the item by following each wire in the object,
divided by the length of all wires in the object
(This is intended to be used for objects like circular loops where there
are many short wires each of the same length)
OR:
feed_wire_index AND feed_alpha_wire
which specify the i'th wire (0 to n-1) in the n wires in the object, and the distance along that
wire divided by that wire's length
   add(geomObj, wireframe_color = 'darkgoldenrod'):
Add a completed component to the specified model: model_name.add(component_name). Any changes made
to the component after this point are ignored.
   write_nec():
Write the entire model to the NEC input file ready for analysis. At this point, the function
"show_wires_from_file" may be used to see the specified geometry in a 3D view.
   run_nec():
Pass the model file to NEC for analysis and wait for the output.
class GeometryObject:
   translate(**params):
Translate an object by dx, dy, dz
Arguments are dx_{units}, dy_{units}, dz_{units}
   rotate_ZtoY():
Rotate the object through 90 degrees around X
   rotate_ZtoX():
Rotate the object through 90 degrees around Y
   rotate_around_X(angle_deg):
Rotate the object through angle_deg degrees around X
   rotate_around_Y(angle_deg):
Rotate the object through angle_deg degrees around Y
   rotate_around_Z(angle_deg):
Rotate the object through angle_deg degrees around Z
   connect_ends(other, tol=1e-3, verbose = False):
Check both ends of the wire to see if they lie on any wires in the specified object,
and if so, split the wires of the specified object so that NEC considers them to be
a valid T junction. Usage is:
wire.connect_ends(object, [tol in m], [verbose])
if verbose is True, details of the wire connection(s) are printed
visualiser.py
   show_wires_from_file(model, n_strands = 8, color = 'darkgoldenrod', alpha = 0.3, view_az = 30, view_el = 30):
Opens the specified nec input file (*.nec) and reads the geometry,
then displays the geometry in a 3D projection. The feed is highligted in red.
Loads are highlighted in green.
optimisers.py
class RandomOptimiser:
Initialise the optimisation parameters. Details to be written - please see examples for help with parameters.
   optimise(verbose=False, tty=True, show_geometry = True):
This random optimiser works by simultaneously adjusting all input parameters by a random multiplier (1 + x)
and comparing the user-specified cost function with the best achieved so far. If the test gives a better
cost, the test is adopted as the new baseline.
Note that of course this won't produce good results for any parameters that start off close to or at
zero and/or have an allowable range with zero close to the middle. Future versions of this optimiser may allow
specifications to make this work, but for now you should arrange for the input parameters and their
likely useful range to be away from zero, by using an offset.
If any parameters seem likely to drift into non-useful ranges, use the 'bounds' specification in the
initialisation to limit their max and min values.
components.py
class components:
Sets object_counter to starting_tag_nr (tags number identifies an object)
and loads the _units module class _units()
   copy_of(existing_obj):
Returns a clone of existing_obj with a new iTag
   wire_Z(**dimensions):
Create a straight wire aligned along the Z-axis, centered at the origin.
The wire extends from -length/2 to +length/2 on the Z-axis, with the specified diameter.
dimensions:
length_{units_string} (float): Length of the wire.
wire_diameter_{units_string} (float): Diameter of the wire.
In each case, the unit suffix (e.g., _mm, _m) must be present in the units class dictionary '_UNIT_FACTORS' (see units.py)
Returns:
obj (GeometryObject): The constructed geometry object with the defined wire.
   rect_loop_XZ(**dimensions):
Create a rectangular wire loop in the XZ plane, centered at the origin, with the specified wire diameter.
The 'side' wires extend from Z=-length/2 to Z=+length/2 at X = +/- width/2.
The 'top/bottom' wires extend from X=-width/2 to X=+width/2 at Z = +/- length/2.
dimensions:
length_{units_string} (float): 'Length' (extension along Z) of the rectangle.
width_{units_string} (float): 'Width' (extension along X) of the rectangle.
wire_diameter_{units_string} (float): Diameter of the wires.
In each case, the unit suffix (e.g., _mm, _m) must be present in the units class dictionary '_UNIT_FACTORS' (see units.py)
Returns:
obj (GeometryObject): The constructed geometry object with the defined wires.
   connector(from_object, from_wire_index, from_alpha_wire, to_object, to_wire_index, to_alpha_wire, wire_diameter_mm = 1.0):
Create a single wire from a specified point on the from_object to a specified point on the to_object.
The point on an object is specified as {ftom|to}_wire_index AND {ftom|to}_alpha_wire, which specify respectively:
the i'th wire in the n wires in the object, and
the distance along that wire divided by that wire's length
Arguments:
from_object (GeometryObject), from_wire_index (int, 0 .. n_wires_in_from_object - 1), from_alpha_wire (float, 0 .. 1)
to_object (GeometryObject), to_wire_index (int, 0 .. n_wires_in_to_object - 1), to_alpha_wire (float, 0 .. 1)
Returns:
obj (GeometryObject): The constructed geometry object with the defined wire.
   helix(wires_per_turn, sense, taper_factor = 1.0, **dimensions):
Create a single helix with axis = Z axis
Arguments_
sense ("LH"|"RH") - the handedness of the helix
wires_per_turn (int) - the number of wires to use to represent the helix, per turn
dimensions:
radius_{units} (float) - helix radius
length_{units} (float) - helix length along Z
pitch_{units} (float) - helix length along Z per whole turn
wire_diameter_{units} (float) - diameter of wire making the helix
In each case above, the units suffix (e.g., _mm, _m) must be present in the units class dictionary '_UNIT_FACTORS' (see units.py)
Returns:
obj (GeometryObject): The constructed geometry object representing the helix.
   flexi_helix(sense, wires_per_turn, n_cos,r_cos_params,p_cos_params, **dimensions):
Create a helix along the Z axis where radius and pitch vary as scaled sums of cosines:
r(Z) = r0 * Σ [RA_i * cos(i * π * Z / l + RP_i)] for i=0..n-1
p(Z) = p0 * Σ [PA_i * cos(i * π * Z / l + PP_i)] for i=0..n-1
The geometry is generated by stepping through helical phase (φ), and computing local radius and pitch from cosine series
as functions of normalized φ (mapped to Z via cumulative pitch integration).
Parameters:
sense (str): "RH" or "LH" handedness
wires_per_turn (int): Resolution (segments per full turn)
n_cos (int): Number of cosine terms
r_cos_params (list of tuples): [(RA0, RP0), ...] radius amplitudes and phases
p_cos_params (list of tuples): [(PA0, PP0), ...] pitch amplitudes and phases
dimensions:
l_{units} (float): Approximate helix length along Z
r0_{units} (float): Base radius scale factor
p0_{units} (float): Base pitch scale factor (length per full turn)
wire_diameter_{units} (float): Wire thickness
Returns:
GeometryObject: The constructed helix geometry object.
   circular_arc(n_wires, arc_phi_deg, **dimensions):
Create a single circular arc in the XY plane centred on the origin
Arguments:
n_wires (int) - the number of wires to use to represent the arc
arc_phi_deg (float) - the angle subtended at the origin by the arc in degrees. Note that a continuous circular loop can be constructed by specifying arc_phi_deg = 360.
dimensions:
radius_{units} (float) - helix radius
wire_diameter_{units} (float) - diameter of wire making the helix
In each case above, the units suffix (e.g., _mm, _m) must be present in the units class dictionary '_UNIT_FACTORS' (see units.py)
Returns:
obj (GeometryObject): The constructed geometry object representing the helix.
   thin_sheet(model, epsillon_r = 1.0, conductivity = 1e12, force_odd = True, close_start = True, close_end = True, close_bottom = True, close_top = True, enforce_exact_pitch = True, **dimensions):
Creates a grid of wires interconnected at segment level to economically model a flat sheet
which is normal to the x axis and extends from z=-height/2 to z= height/2, and y = -length/2 to length/2
Models *either* conductive or dielectric sheet, not both:
Set epsillon_r to 1.0 for conducting sheet
Set epsillon_r > 1.0 for dielectric sheet
Arguments:
model - the object model being built
epsillon_r - relative dielectric constant
force_odd = true ensures wires cross at y=z=0
The four 'close_' parameters determine whether or not the edges are 'sealed' with a final wire (if True) or
not (if False) so that the grid can be joined to other grids without wires overlapping:
close_end = True completes the grid with a final end z wire at y = length/2
close_start = True starts the grid with a z wire at y = -length/2
close_top = True completes the grid with a y wire at z = height/2
close_bottom = True starts the grid with a y wire at z = -height/2
enforce_exact_pitch: if True, length and height are adjusted to fit an integer number
of grid cells of the specified pitch. If False, length and height remain as specified and
the grid pitch in Y and Z is adjusted to fit the number of grid cells calculated from the
grid pitch and force_odd value. Behaviour prior to V2.0.3 was enforce_exact_pitch.
Required dimensions are:
length_
height_
grid_pitch_
dielectric_thickness_ (for dielectric sheets only)
Optional dimensions are:
conducting_wire_diameter_ (for conducting sheets only, default is 1mm)
Made with Docu-lite 1.5.1 by Alan Robinson: github.com/G1OJS/docu-lite/