# Copyright (C) 2023 - 2024 ANSYS, Inc. and/or its affiliates.
# SPDX-License-Identifier: MIT
#
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in all
# copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.
import copy
import math
import os
import ansys.aedt.core.generic.constants as constants
from ansys.aedt.core.generic.general_methods import generate_unique_name
from ansys.aedt.core.generic.general_methods import pyaedt_function_handler
from ansys.aedt.toolkits.antenna.backend.antenna_models.parameters import InputParameters
from ansys.aedt.toolkits.antenna.backend.antenna_models.parameters import Property
from ansys.aedt.toolkits.antenna.backend.antenna_models.parameters import SynthesisParameters
from ansys.aedt.toolkits.antenna.backend.models import properties
class CommonAntenna(object):
"""Provides base methods common to the antenna toolkit."""
antenna_type = ""
def __init__(self, default_input_parameters, *args, **kwargs):
self._app = args[0]
self._input_parameters = InputParameters(default_input_parameters)
for k, v in kwargs.items():
if k in default_input_parameters:
setattr(self._input_parameters, k, copy.deepcopy(v))
else:
raise AttributeError(
f"{k} is not a valid parameter for this antenna. \n"
f"Accepted parameters are {str(list(default_input_parameters.keys()))}"
)
if self._input_parameters.length_unit is None:
self._input_parameters.length_unit = properties.antenna.synthesis.length_unit
if self._app:
self._input_parameters.name = self._check_antenna_name(self._input_parameters.name)
self.synthesis_parameters = SynthesisParameters()
self.synthesis_parameters.name = self._input_parameters.name
self.object_list = {}
self.boundaries = {}
self.excitations = {}
self.mesh_operations = {}
@property
def material(self):
"""Material assigned.
Returns
-------
str
"""
return self._input_parameters.material
@material.setter
def material(self, value):
self._input_parameters.material = value
if self.object_list:
parameters = self.synthesis()
self.update_synthesis_parameters(parameters)
self.set_variables_in_hfss()
@property
def frequency(self):
"""Center frequency.
Returns
-------
float
"""
return self._input_parameters.frequency
@frequency.setter
def frequency(self, value):
self._input_parameters.frequency = value
parameters = self.synthesis()
self.update_synthesis_parameters(parameters)
if self.object_list:
self.set_variables_in_hfss()
@property
def frequency_unit(self):
"""Frequency units.
Returns
-------
str
"""
return self._input_parameters.frequency_unit
@frequency_unit.setter
def frequency_unit(self, value):
self._input_parameters.frequency_unit = value
parameters = self.synthesis()
self.update_synthesis_parameters(parameters)
if self.object_list:
self.set_variables_in_hfss()
@property
def outer_boundary(self):
"""Outer boundary.
Returns
-------
str
"""
return self._input_parameters.outer_boundary
@outer_boundary.setter
def outer_boundary(self, value):
self._input_parameters.outer_boundary = value
if self.object_list:
self._app.create_open_region(
str(self.frequency) + self.frequency_unit,
value,
)
@property
def length_unit(self):
"""Length unit.
Returns
-------
str
"""
return self._input_parameters.length_unit
@length_unit.setter
def length_unit(self, value):
self._input_parameters.length_unit = value
parameters = self.synthesis()
self.update_synthesis_parameters(parameters)
if self.object_list:
self.set_variables_in_hfss()
@property
def coordinate_system(self):
"""Reference coordinate system.
Returns
-------
str
"""
return self._input_parameters.coordinate_system
@coordinate_system.setter
def coordinate_system(self, value):
self._input_parameters.coordinate_system = value
for antenna_obj in self.object_list:
self.object_list[antenna_obj].history().props[
"Coordinate System"
] = self._input_parameters.coordinate_system
@property
def name(self):
"""Antenna name.
Returns
-------
str
"""
return self._input_parameters.name
@name.setter
def name(self, value):
if value != self.name and self.object_list:
for antenna_obj in self.object_list:
self.object_list[antenna_obj].group_name = value
if len(list(self._app.modeler.oeditor.GetObjectsInGroup(self.name))) == 0:
self._app.modeler.oeditor.Delete(["NAME:Selections", "Selections:=", self.name])
self._input_parameters.name = value
@property
def origin(self):
"""Antenna origin.
Returns
-------
list
"""
return self._input_parameters.origin
@origin.setter
def origin(self, value):
self._input_parameters.origin = value
if self.object_list:
parameters = self.synthesis()
self.update_synthesis_parameters(parameters)
self.set_variables_in_hfss()
@pyaedt_function_handler()
def create_lattice_pair(self, lattice_height=None, bottom_extend=False):
"""Create a lattice pair box.
Parameters
----------
lattice_height : str, optional
Height of the lattice pair box.
bottom_extend : bool, optional
Whether to extend the lattice pair in the bottom side. The default is ``False``.
Returns
-------
:class:`ansys.aedt.core.modeler.object3d.Object3d`
3D object.
Examples
--------
>>> from ansys.aedt.core import Hfss
>>> from ansys.aedt.toolkits.antenna.backend.antenna_models.horn import Conical
>>> hfss = Hfss()
>>> horn = hfss.add_from_toolkit(Conical, draw=True)
>>> horn = horn.create_lattice_pair(lattice_height="20mm")
"""
if not lattice_height:
lightSpeed = constants.SpeedOfLight # m/s
freq_hz = constants.unit_converter(self.frequency, "Freq", self.frequency_unit, "Hz")
wavelength = lightSpeed / freq_hz
lattice_height = str(wavelength / 10.0) + "meter"
self.synthesis_parameters.add_parameter("lattice_height", lattice_height)
hfss_parameter = self.synthesis_parameters.lattice_height.hfss_variable
self._app[hfss_parameter] = self.synthesis_parameters.lattice_height.value
bounding_box = self._app.modeler.get_group_bounding_box(self.name)
bounding_dim = [
abs(bounding_box[0] - bounding_box[3]),
abs(bounding_box[1] - bounding_box[4]),
abs(bounding_box[2] - bounding_box[5]),
]
if bottom_extend:
lattice_box = self._app.modeler.create_box(
origin=[
str(bounding_box[0]) + self._app.modeler.model_units,
str(bounding_box[1]) + self._app.modeler.model_units,
str(bounding_box[2]) + self._app.modeler.model_units + "-" + hfss_parameter,
],
sizes=[
str(bounding_dim[0]) + self._app.modeler.model_units,
str(bounding_dim[1]) + self._app.modeler.model_units,
str(bounding_dim[2]) + self._app.modeler.model_units + "+2*" + hfss_parameter,
],
material="vacuum",
)
else:
lattice_box = self._app.modeler.create_box(
origin=[
str(bounding_box[0]) + self._app.modeler.model_units,
str(bounding_box[1]) + self._app.modeler.model_units,
str(bounding_box[2]) + self._app.modeler.model_units,
],
sizes=[
str(bounding_dim[0]) + self._app.modeler.model_units,
str(bounding_dim[1]) + self._app.modeler.model_units,
str(bounding_dim[2]) + self._app.modeler.model_units + "+" + hfss_parameter,
],
material="vacuum",
)
lattice1 = self._app.assign_lattice_pair(face_couple=[lattice_box.bottom_face_x.id, lattice_box.top_face_x.id])
self.boundaries[lattice1.name] = lattice1
lattice2 = self._app.assign_lattice_pair(face_couple=[lattice_box.bottom_face_y.id, lattice_box.top_face_y.id])
self.boundaries[lattice2.name] = lattice2
self.object_list[lattice_box.name] = lattice_box
return lattice_box
@pyaedt_function_handler()
def create_3dcomponent(self, component_file=None, component_name=None, replace=False):
"""Create a 3D component of the antenna.
Parameters
----------
component_file : str, optional
Full path to the A3DCOMP file. The default is the ``ansys.aedt.core`` folder.
component_name : str, optional
Name of the component. The default is the antenna name.
replace : bool, optional
Whether to eplace the antenna with a 3D component. The default is ``False``.
Returns
-------
str
Path of the 3D component file or
:class:`ansys.aedt.core.modeler.components_3d.UserDefinedComponent`.
Examples
--------
>>> from ansys.aedt.core import Hfss
>>> from ansys.aedt.toolkits.antenna.backend.antenna_models.horn import Conical
>>> hfss = Hfss()
>>> horn = hfss.add_from_toolkit(Conical, draw=True)
>>> horn = horn.create_3dcomponent()
"""
if not component_file:
component_file = os.path.join(self._app.working_directory, self.name + ".a3dcomp")
if not component_name:
component_name = self.name
parameters = []
for p in self.synthesis_parameters.__dict__.values():
if isinstance(p, Property):
parameters.append(p.hfss_variable)
boundaries = list(self.boundaries.keys())
if not boundaries:
boundaries = [""]
self._app.modeler.create_3dcomponent(
input_file=component_file,
name=component_name,
variables_to_include=parameters,
assignment=list(self.object_list.keys()),
boundaries=boundaries,
excitations=list(self.excitations.keys()),
coordinate_systems=[self.coordinate_system],
reference_coordinate_system=self.coordinate_system,
component_outline="None",
)
if replace:
user_defined_component = self._app.modeler.replace_3dcomponent(
name=component_name,
variables_to_include=parameters,
assignment=list(self.object_list.keys()),
boundaries=boundaries,
excitations=list(self.excitations.keys()),
coordinate_systems=[self.coordinate_system],
reference_coordinate_system=self.coordinate_system,
)
if self._app.modeler.oeditor.GetObjectsInGroup(self.name).count == 0:
self._app.modeler.oeditor.Delete(["NAME:Selections", "Selections:=", self.name])
return user_defined_component
return component_file
@pyaedt_function_handler()
def duplicate_along_line(self, vector, num_clones=2):
"""Duplicate the object along a line.
Parameters
----------
vector : list
List of ``[x1 ,y1, z1]`` coordinates for the vector.
num_clones : int, optional
Number of clones. The default is ``2``.
Returns
-------
dict
Dictionary with the list of new objects.
Examples
--------
>>> from ansys.aedt.core import Hfss
>>> from ansys.aedt.toolkits.antenna.backend.antenna_models.horn import Conical
>>> hfss = Hfss()
>>> horn = hfss.add_from_toolkit(Conical, draw=True)
>>> new_horn = horn.duplicate_along_line([10, 0, 0], 2)
"""
new_objects = {}
for i in range(0, num_clones - 1):
new_objects["antenna" + str(i)] = []
for component in self.object_list:
_, output = self._app.modeler.duplicate_along_line(component, vector, num_clones)
for i in range(0, num_clones - 1):
new_objects["antenna" + str(i)].append(output[i])
return new_objects
@pyaedt_function_handler()
def _update_parameters(self, parameters, length_unit):
for param in parameters:
self._app[param] = str(parameters[param]) + length_unit
return True
@pyaedt_function_handler()
def synthesis(self):
pass
@pyaedt_function_handler()
def _check_antenna_name(self, antenna_name=None):
"""Check if antenna name is repeated or assign a random antenna name."""
if (
not antenna_name
or len(list(self._app.modeler.oeditor.GetObjectsInGroup(antenna_name))) > 0
or any(antenna_name in variables for variables in list(self._app.variable_manager.variables.keys()))
):
antenna_name = generate_unique_name(self.antenna_type)
if self._app:
while len(list(self._app.modeler.oeditor.GetObjectsInGroup(antenna_name))) > 0:
antenna_name = generate_unique_name(self.antenna_type)
return antenna_name
@pyaedt_function_handler()
def update_synthesis_parameters(self, new_params):
"""Update the synthesis parameter from the antenna list."""
for k, v in new_params.items():
if hasattr(self.synthesis_parameters, k):
param = getattr(self.synthesis_parameters, k)
param.value = float(round(v, 6))
else:
self.synthesis_parameters.add_parameter(k, v)
@pyaedt_function_handler()
def set_variables_in_hfss(self, not_used=None):
"""Create HFSS design variables."""
if not not_used:
not_used = []
for p in self.synthesis_parameters.__dict__.values():
if isinstance(p, Property) and p.hfss_variable not in not_used:
properties.antenna.parameters_hfss[p.name] = p.hfss_variable
if "angle" in p.hfss_variable:
self._app[p.hfss_variable] = str(p.value) + "deg"
elif "ratio" in p.hfss_variable:
self._app[p.hfss_variable] = str(p.value)
else:
self._app[p.hfss_variable] = str(p.value) + self.length_unit
@pyaedt_function_handler()
def init_model(self):
"""Create a radiation boundary."""
if self._input_parameters.outer_boundary:
self._app.create_open_region(str(self.frequency) + self.frequency_unit, self.outer_boundary)
@pyaedt_function_handler()
def setup_hfss(self):
"""Set up an antenna in HFSS."""
for obj_name in self.object_list.keys():
if obj_name.startswith("PerfE") or obj_name.startswith("gnd_") or obj_name.startswith("ant_"):
bound = self._app.assign_perfecte_to_sheets(obj_name)
bound.name = "PerfE_" + obj_name
self.boundaries[bound.name] = bound
elif obj_name.startswith("coax"):
obj = self.object_list[obj_name]
face_id = obj.faces[0].edges[0].id
for face in obj.faces:
if len(face.edges) == 2:
face_id = face.id
break
coax_bound = self._app.assign_perfecte_to_sheets(face_id)
coax_bound.name = "PerfE_" + obj_name
self.boundaries[coax_bound.name] = coax_bound
break
port_count = 1
for item in list(self.object_list.keys()):
terminal_references = []
port_lump = port = port_cap = None
if "port_lump_{}".format(self.name) in item:
port_lump = self.object_list[item]
terminal_references = [
i
for i in port_lump.touching_objects
if self._app.modeler[i]
and (
self._app.modeler[i].object_type == "Sheet"
or self._app.materials[self._app.modeler[i].material_name].is_conductor()
)
]
if len(terminal_references) > 1:
axis_dir = [[], []]
for edge in port_lump.edges:
if terminal_references[1] in self._app.modeler.get_bodynames_from_position(edge.midpoint):
axis_dir[1] = edge.midpoint
elif terminal_references[0] in self._app.modeler.get_bodynames_from_position(edge.midpoint):
axis_dir[0] = edge.midpoint
terminal_references = terminal_references[1:]
elif "port_{}".format(self.name) in item:
port = self.object_list[item]
for item_cap in list(self.object_list.keys()):
if "port_cap_{}".format(self.name) in item_cap:
port_cap = self.object_list[item_cap]
if port_lump:
port1 = self._app.lumped_port(
assignment=item,
reference=terminal_references,
impedance=50,
name="port_" + self.name + "_" + str(port_count),
renormalize=True,
deembed=False,
)
self.excitations[port1.name] = port1
port_count += 1
elif port:
if self._app.solution_type == "Terminal" and port_cap:
terminal_references = port_cap.name
port1 = self._app.wave_port(
assignment=port,
reference=terminal_references,
name="port_" + self.name + "_" + str(port_count),
)
self.excitations[port1.name] = port1
port_count += 1
return True
[docs]
class TransmissionLine(object):
"""Provides base methods common to transmission line calculations.
Parameters
----------
frequency : float, optional
Center frequency. The default is ``10.0``.
frequency_unit : str, optional
Frequency units. The default is ``"GHz"``.
Returns
-------
:class:`aedt.toolkits.antenna.common.TransmissionLine`
Transmission line calculator object.
Examples
--------
>>> from ansys.aedt.toolkits.antenna.backend.antenna_models.common import TransmissionLine
>>> tl_calc = TransmissionLine(frequency=2)
>>> tl_calc.stripline_calculator(substrate_height=10, permittivity=2.2, impedance=60)
"""
def __init__(self, frequency=10, frequency_unit="GHz"):
self.frequency = frequency
self.frequency_unit = frequency_unit
[docs]
@pyaedt_function_handler()
def microstrip_calculator(self, substrate_height, permittivity, impedance=50.0, electrical_length=150.0):
"""Use the micro strip line calculator to calculate line width and length.
Parameters
----------
substrate_height : float
Substrate height.
permittivity : float
Substrate permittivity.
impedance : str, optional
Impedance. The default is ``50.0``.
electrical_length : str, optional
Electrical length in degrees. The default is ``150.0``.
Returns
-------
tuple
Line width and length.
"""
z0 = impedance
e0 = permittivity
h0 = substrate_height
A_us = z0 / 60.0 * math.sqrt((e0 + 1.0) / 2.0) + (e0 - 1.0) / (e0 + 1.0) * (0.23 + 0.11 / e0)
B_us = 377.0 * math.pi / (2.0 * z0 * math.sqrt(e0))
w_over_subH_1 = 8.0 * math.exp(A_us) / (math.exp(2.0 * A_us) - 2.0)
w_over_subH_2 = (
2.0
/ math.pi
* (
B_us
- 1.0
- math.log(2.0 * B_us - 1.0)
+ (e0 - 1.0) / (2.0 * e0) * (math.log(B_us - 1.0) + 0.39 - 0.61 / e0)
)
)
ustrip_width = w_over_subH_1 * h0
if w_over_subH_1 < 2.0:
ustrip_width = w_over_subH_1 * h0
if w_over_subH_2 >= 2:
ustrip_width = w_over_subH_2 * h0
er_eff = (e0 + 1.0) / 2.0 + (e0 - 1.0) / 2.0 * 1.0 / (math.sqrt(1.0 + 12.0 * h0 / ustrip_width))
f = constants.unit_converter(self.frequency, "Freq", self.frequency_unit, "Hz")
k0 = 2.0 * math.pi * f / 3.0e8
ustrip_length = math.radians(electrical_length) / (math.sqrt(er_eff) * k0)
return ustrip_width, ustrip_length
[docs]
@pyaedt_function_handler()
def stripline_calculator(self, substrate_height, permittivity, impedance=50.0):
"""Use the strip line calculator to calculate line width.
Parameters
----------
substrate_height : float
Substrate height.
permittivity : float
Substrate permittivity.
impedance : str, optional
Impedance. The default is ``50.0``.
Returns
-------
float
Line width.
"""
x = 30.0 * math.pi / (math.sqrt(permittivity) * impedance) - 0.441
if math.sqrt(permittivity) * impedance <= 120:
w_over_h = x
else:
w_over_h = 0.85 - math.sqrt(0.6 - x)
width = w_over_h * substrate_height
return width
[docs]
@pyaedt_function_handler()
def suspended_strip_calculator(self, wavelength, w1, substrate_height, permittivity):
"""Use the suspended strip line calculator to calculate effective permittivity.
Parameters
----------
wavelength : float
w1 : float
substrate_height : float
Substrate in meter.
permittivity : float
Dielectric permittivity
Returns
-------
float
Effective permittivity.
"""
Hfrac = 16.0 # H_as_fraction_of_wavelength 1/H
H = (wavelength / math.sqrt(permittivity) + substrate_height * Hfrac) / Hfrac
heigth_ratio = substrate_height / (H - substrate_height)
a = math.pow(0.8621 - 0.125 * math.log(heigth_ratio), 4.0)
b = math.pow(0.4986 - 0.1397 * math.log(heigth_ratio), 4.0)
Width_to_height_ratio = w1 / (H - substrate_height)
sqrt_er_eff = math.pow(
1.0 + heigth_ratio * (a - b * math.log(Width_to_height_ratio)) * (1.0 / math.sqrt(permittivity) - 1.0),
-1.0,
)
effective_permittivity = math.pow(sqrt_er_eff, 2.0)
if (permittivity >= 6.0) and (permittivity <= 10.0):
effective_permittivity = effective_permittivity * 1.15 # about 15% larger than calculated
if permittivity > 10:
effective_permittivity = effective_permittivity * 1.25 # about 25% lager then calculated
if effective_permittivity >= (permittivity + 1.0) / 2.0:
effective_permittivity = (permittivity + 1.0) / 2.0
return effective_permittivity
[docs]
class StandardWaveguide(object):
"""Provides base methods common to standard waveguides.
Parameters
----------
frequency : float, optional
Center frequency. The default is ``10.0``.
frequency_unit : str, optional
Frequency units. The default is ``"GHz"``.
Returns
-------
:class:`aedt.toolkits.antenna.common.StandardWaveguide`
Standard waveguide object.
Examples
--------
>>> from ansys.aedt.toolkits.antenna.common import StandardWaveguide
>>> wg_calc = StandardWaveguide()
>>> wg_dim = wg_calc.get_waveguide_dimensions("WR-75")
"""
wg = {}
wg["WR-2300"] = [23.0, 11.5, 0.15]
wg["WR-2100"] = [21.0, 10.5, 0.125]
wg["WR-1800"] = [18.0, 9.0, 0.125]
wg["WR-1500"] = [15.0, 7.5, 0.125]
wg["WR-1150"] = [11.5, 5.75, 0.125]
wg["WR-975"] = [9.75, 4.875, 0.125]
wg["WR-770"] = [7.7, 3.850, 0.125]
wg["WR-650"] = [6.5, 3.25, 0.08]
wg["WR-510"] = [5.1, 2.55, 0.08]
wg["WR-430"] = [4.3, 2.15, 0.08]
wg["WR-340"] = [3.4, 1.7, 0.08]
wg["WR-284"] = [2.84, 1.34, 0.08]
wg["WR-229"] = [2.29, 1.145, 0.064]
wg["WR-187"] = [1.872, 0.872, 0.064]
wg["WR-159"] = [1.53, 0.795, 0.064]
wg["WR-137"] = [1.372, 0.622, 0.064]
wg["WR-112"] = [1.122, 0.497, 0.064]
wg["WR-102"] = [1.02, 0.51, 0.064]
wg["WR-90"] = [0.9, 0.4, 0.05]
wg["WR-75"] = [0.75, 0.375, 0.05]
wg["WR-62"] = [0.622, 0.311, 0.04]
wg["WR-51"] = [0.51, 0.255, 0.04]
wg["WR-42"] = [0.42, 0.17, 0.04]
wg["WR-34"] = [0.34, 0.17, 0.04]
wg["WR-28"] = [0.28, 0.14, 0.04]
wg["WR-22"] = [0.224, 0.112, 0.04]
wg["WR-19"] = [0.188, 0.094, 0.04]
wg["WR-15"] = [0.148, 0.074, 0.04]
wg["WR-12"] = [0.122, 0.061, 0.04]
wg["WR-10"] = [0.1, 0.05, 0.04]
wg["WR-8"] = [0.08, 0.04, 0.02]
wg["WR-7"] = [0.065, 0.0325, 0.02]
wg["WR-5"] = [0.0510, 0.0255, 0.02]
def __init__(self, frequency=10, frequency_unit="GHz"):
self.frequency = frequency
self.frequency_unit = frequency_unit
@property
def waveguide_list(self):
"""Standard waveguide list."""
return self.wg.keys()
[docs]
@pyaedt_function_handler()
def get_waveguide_dimensions(self, name, units="mm"):
"""Get waveguide dimensions.
Parameters
----------
name : str
Waveguide name.
units : str
Dimension units. The default is ``mm``.
Returns
-------
list
Waveguide dimensions.
"""
if name in self.wg:
wg_dim = []
for dbl in self.wg[name]:
wg_dim.append(constants.unit_converter(dbl, "Length", "in", units))
return wg_dim
else:
return False
[docs]
@pyaedt_function_handler()
def find_waveguide(self, freq, units="GHz"): # pragma: no cover
"""Find the closest standard waveguide for the operational frequency.
Parameters
----------
freq : float
Operational frequency.
units : str
Input frequency units. The default is ``"GHz"``.
Returns
-------
str
Waveguide name.
"""
freq = constants.unit_converter(freq, "Frequency", units, "GHz")
op_freq = freq * 0.8
if op_freq >= 140:
wg_name = "WR-5"
elif op_freq >= 110:
wg_name = "WR-7"
elif op_freq >= 90:
wg_name = "WR-8"
elif op_freq >= 75:
wg_name = "WR-10"
elif op_freq >= 60:
wg_name = "WR-12"
elif op_freq >= 50:
wg_name = "WR-15"
elif op_freq >= 40:
wg_name = "WR-19"
elif op_freq >= 33:
wg_name = "WR-22"
elif op_freq >= 26.50:
wg_name = "WR-28"
elif op_freq >= 22:
wg_name = "WR-34"
elif op_freq >= 18:
wg_name = "WR-42"
elif op_freq >= 15:
wg_name = "WR-51"
elif op_freq >= 12.4:
wg_name = "WR-62"
elif op_freq >= 10:
wg_name = "WR-75"
elif op_freq >= 8.2:
wg_name = "WR-90"
elif op_freq >= 6.95:
wg_name = "WR-102"
elif op_freq >= 7.05:
wg_name = "WR-112"
elif op_freq >= 5.85:
wg_name = "WR-137"
elif op_freq >= 4.9:
wg_name = "WR-159"
elif op_freq >= 3.95:
wg_name = "WR-187"
elif op_freq >= 3.3:
wg_name = "WR-229"
elif op_freq >= 2.6:
wg_name = "WR-284"
elif op_freq >= 2.2:
wg_name = "WR-340"
elif op_freq >= 1.70:
wg_name = "WR-430"
elif op_freq >= 1.45:
wg_name = "WR-510"
elif op_freq >= 1.12:
wg_name = "WR-650"
elif op_freq >= 0.96:
wg_name = "WR-770"
elif op_freq >= 0.75:
wg_name = "WR-975"
elif op_freq >= 0.64:
wg_name = "WR-1150"
elif op_freq >= 0.49:
wg_name = "WR-1500"
elif op_freq >= 0.41:
wg_name = "WR-1800"
elif op_freq >= 0.35:
wg_name = "WR-2100"
elif op_freq > 0:
wg_name = "WR-2300"
else:
wg_name = None
return wg_name