# 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.
from collections import OrderedDict
import ansys.aedt.core.generic.constants as constants
from ansys.aedt.core.generic.general_methods import pyaedt_function_handler
from ansys.aedt.toolkits.common.backend.logger_handler import logger
from ansys.aedt.toolkits.antenna.backend.antenna_models.common import CommonAntenna
from ansys.aedt.toolkits.antenna.backend.antenna_models.common import StandardWaveguide
class CommonHorn(CommonAntenna):
"""Provides base methods common to horn antenna."""
def __init__(self, _default_input_parameters, *args, **kwargs):
CommonAntenna.antenna_type = "Horn"
CommonAntenna.__init__(self, _default_input_parameters, *args, **kwargs)
@property
def material(self):
"""Horn material.
Returns
-------
str
"""
return self._input_parameters.material
@material.setter
def material(self, value):
if self._app:
if (
value
and value not in self._app.materials.mat_names_aedt
and value not in self._app.materials.mat_names_aedt_lower
):
logger.debug("Material not defined")
else:
if value != self.material and self.object_list:
for antenna_obj in self.object_list:
if (
self.object_list[antenna_obj].material_name == self.material.lower()
and "coax" not in antenna_obj
):
self.object_list[antenna_obj].material_name = value
self._input_parameters.material = value
parameters = self.synthesis()
self.update_synthesis_parameters(parameters)
self.set_variables_in_hfss()
else:
self._input_parameters.material = value
@property
def material_properties(self):
"""Substrate material properties.
Returns
-------
str
"""
return self._input_parameters.material_properties
@pyaedt_function_handler()
def synthesis(self):
pass
[docs]
class Conical(CommonHorn):
"""Manages a conical horn antenna.
This class is accessible through the app hfss object [1]_.
Parameters
----------
frequency : float, optional
Center frequency. The default is ``10.0``.
frequency_unit : str, optional
Frequency units. The default is ``"GHz"``.
material : str, optional
Horn material. If a material is not defined, a new material, ``parametrized``, is defined.
The default is ``"pec"``.
outer_boundary : str, optional
Boundary type to use. The default is ``None``. Options are ``"FEBI"``, ``"PML"``,
``"Radiation"``, and ``None``.
length_unit : str, optional
Length units. The default is ``"mm"``.
parametrized : bool, optional
Whether to create a parametrized antenna. The default is ``True``.
Returns
-------
:class:`aedt.toolkits.antenna.ConicalHorn`
Conical horn object.
Notes
-----
.. [1] C. Balanis, "Aperture Antennas: Analysis, Design, and Applications,"
*Modern Antenna Handbook*, New York, 2008.
Examples
--------
>>> from ansys.aedt.toolkits.antenna.backend.antenna_models.horn import Conical
>>> import ansys.aedt.core
>>> oantenna1 = Conical(None)
>>> oantenna1.frequency = 12.0
>>> app = ansys.aedt.core.Hfss()
>>> oantenna1 = Conical(app)
>>> oantenna1.model_hfss()
>>> oantenna1.setup_hfss()
>>> oantenna2 = Conical(app, origin=[0.2, 0.5, 0])
>>> oantenna2.model_hfss()
>>> oantenna2.setup_hfss()
>>> app.release_desktop(False, False)
"""
_default_input_parameters = {
"name": "",
"origin": [0, 0, 0],
"length_unit": None,
"coordinate_system": "Global",
"frequency": 10.0,
"frequency_unit": "GHz",
"material": "pec",
"outer_boundary": "",
}
def __init__(self, *args, **kwargs):
CommonHorn.__init__(self, self._default_input_parameters, *args, **kwargs)
self._parameters = self.synthesis()
self.update_synthesis_parameters(self._parameters)
self.antenna_type = "Conical"
[docs]
@pyaedt_function_handler()
def synthesis(self):
"""Antenna synthesis.
Returns
-------
dict
Analytical parameters.
"""
parameters = {}
lightSpeed = constants.SpeedOfLight # m/s
freq_hz = constants.unit_converter(self.frequency, "Freq", self.frequency_unit, "Hz")
wavelength = lightSpeed / freq_hz
wavelength_in = constants.unit_converter(wavelength, "Length", "meter", "in")
wg_radius_in = 0.5 * wavelength_in
wg_length_in = 0.4 * wavelength_in
horn_radius_in = 1.4 * wavelength_in
horn_length_in = 2 * wavelength_in
wall_thickness_in = 0.02 * wavelength_in
wg_radius = constants.unit_converter(wg_radius_in, "Length", "in", self.length_unit)
parameters["wg_radius"] = wg_radius
wg_length = constants.unit_converter(wg_length_in, "Length", "in", self.length_unit)
parameters["wg_length"] = wg_length
horn_radius = constants.unit_converter(horn_radius_in, "Length", "in", self.length_unit)
parameters["horn_radius"] = horn_radius
horn_length = constants.unit_converter(horn_length_in, "Length", "in", self.length_unit)
parameters["horn_length"] = horn_length
wall_thickness = constants.unit_converter(wall_thickness_in, "Length", "in", self.length_unit)
parameters["wall_thickness"] = wall_thickness
parameters["pos_x"] = self.origin[0]
parameters["pos_y"] = self.origin[1]
parameters["pos_z"] = self.origin[2]
myKeys = list(parameters.keys())
myKeys.sort()
parameters_out = OrderedDict([(i, parameters[i]) for i in myKeys])
return parameters_out
[docs]
@pyaedt_function_handler()
def model_hfss(self):
"""Draw a conical horn antenna.
Once the antenna is created, this method is not used anymore."""
if self.object_list:
logger.debug("This antenna already exists")
return False
if (
self.material not in self._app.materials.mat_names_aedt
and self.material not in self._app.materials.mat_names_aedt_lower
):
self._app.logger.warning("Material not found. Create the material before assigning it.")
return False
self.set_variables_in_hfss()
# Solution type: Modal
self._app.solution_type = "Modal"
# Map parameters
horn_length = self.synthesis_parameters.horn_length.hfss_variable
horn_radius = self.synthesis_parameters.horn_radius.hfss_variable
wall_thickness = self.synthesis_parameters.wall_thickness.hfss_variable
wg_length = self.synthesis_parameters.wg_length.hfss_variable
wg_radius = self.synthesis_parameters.wg_radius.hfss_variable
pos_x = self.synthesis_parameters.pos_x.hfss_variable
pos_y = self.synthesis_parameters.pos_y.hfss_variable
pos_z = self.synthesis_parameters.pos_z.hfss_variable
antenna_name = self.name
coordinate_system = self.coordinate_system
# Negative air
neg_air = self._app.modeler.create_cylinder(
orientation=2,
origin=["0", "0", "0"],
radius=wg_radius,
height="-" + wg_length,
material="vacuum",
)
neg_air.history().props["Coordinate System"] = coordinate_system
# Wall
wall = self._app.modeler.create_cylinder(
orientation=2,
origin=["0", "0", "0"],
radius=wg_radius + "+" + wall_thickness,
height="-" + wg_length,
name="wg_outer_" + antenna_name,
material=self.material,
)
wall.history().props["Coordinate System"] = coordinate_system
# Subtract
new_wall = self._app.modeler.subtract(tool_list=[neg_air.name], blank_list=[wall.name], keep_originals=False)
# Input
wg_in = self._app.modeler.create_cylinder(
orientation=2,
origin=["0", "0", "0"],
radius=wg_radius,
height="-" + wg_length,
name="wg_inner_" + antenna_name,
material="vacuum",
)
wg_in.history().props["Coordinate System"] = coordinate_system
# Cap
cap = self._app.modeler.create_cylinder(
orientation=2,
origin=["0", "0", "-" + wg_length],
radius=wg_radius + "+" + wall_thickness,
height="-" + wall_thickness,
name="port_cap_" + antenna_name,
material="pec",
)
cap.history().props["Coordinate System"] = coordinate_system
# P1
p1 = self._app.modeler.create_circle(
cs_plane=2,
origin=["0", "0", "-" + wg_length],
radius=wg_radius,
name="port_" + antenna_name,
)
p1.color = (128, 0, 0)
p1.history().props["Coordinate System"] = coordinate_system
# Horn wall
base = self._app.modeler.create_circle(
cs_plane=2,
origin=["0", "0", "0"],
radius=wg_radius,
)
base.history().props["Coordinate System"] = coordinate_system
base_wall = self._app.modeler.create_circle(
cs_plane=2,
origin=["0", "0", "0"],
radius=wg_radius + "+" + wall_thickness,
)
base_wall.history().props["Coordinate System"] = coordinate_system
horn_top = self._app.modeler.create_circle(
cs_plane=2,
origin=["0", "0", horn_length],
radius=horn_radius,
)
horn_top.history().props["Coordinate System"] = coordinate_system
horn_sheet = self._app.modeler.create_circle(
cs_plane=2,
origin=["0", "0", horn_length],
radius=horn_radius + "+" + wall_thickness,
)
horn_sheet.history().props["Coordinate System"] = coordinate_system
self._app.modeler.connect([horn_sheet.name, base_wall.name])
self._app.modeler.connect([base.name, horn_top.name])
# Horn
self._app.modeler.subtract(blank_list=[horn_sheet.name], tool_list=[base.name], keep_originals=False)
self._app.modeler.unite([horn_sheet.name, wall.name])
air_base = self._app.modeler.create_circle(
cs_plane=2,
origin=["0", "0", "0"],
radius=wg_radius,
)
air_base.history().props["Coordinate System"] = coordinate_system
air_top = self._app.modeler.create_circle(
cs_plane=2,
origin=["0", "0", horn_length],
radius=horn_radius,
)
air_top.history().props["Coordinate System"] = coordinate_system
self._app.modeler.connect([air_base, air_top])
self._app.modeler.unite([wg_in, air_base])
wg_in.name = "internal_" + antenna_name
wg_in.color = (128, 255, 255)
horn_sheet.name = "metal_" + antenna_name
horn_sheet.material_name = self.material
horn_sheet.color = (255, 128, 65)
cap.color = (132, 132, 192)
p1.color = (128, 0, 0)
self.object_list[wg_in.name] = wg_in
self.object_list[horn_sheet.name] = horn_sheet
self.object_list[cap.name] = cap
self.object_list[p1.name] = p1
self._app.modeler.move(list(self.object_list.keys()), [pos_x, pos_y, pos_z])
wg_in.group_name = antenna_name
horn_sheet.group_name = antenna_name
cap.group_name = antenna_name
p1.group_name = antenna_name
[docs]
@pyaedt_function_handler()
def model_disco(self):
"""Model in PyDiscovery. To be implemented."""
pass
[docs]
@pyaedt_function_handler()
def setup_disco(self):
"""Set up in PyDiscovery. To be implemented."""
pass
[docs]
class PyramidalRidged(CommonHorn):
"""Manages a pyramidal ridged horn antenna.
This class is accessible through the app hfss object [1]_.
Parameters
----------
frequency : float, optional
Center frequency. The default is ``10.0``.
frequency_unit : str, optional
Frequency units. The default is ``"GHz"``.
material : str, optional
Horn material. If a material is not defined, a new material, ``parametrized``, is defined.
The default is ``"pec"``.
outer_boundary : str, optional
Boundary type to use. The default is ``None``. Options are ``"FEBI"``, ``"PML"``,
``"Radiation"``, and ``None``.
length_unit : str, optional
Length units. The default is ``"mm"``.
parametrized : bool, optional
Whether to create a parametrized antenna. The default is ``True``.
Returns
-------
:class:`aedt.toolkits.antenna.PyramidalRidged`
Pyramidal ridged horn object.
Notes
-----
.. [1] C. Balanis, "Aperture Antennas: Analysis, Design, and Applications,"
*Modern Antenna Handbook*, New York, 2008.
Examples
--------
>>> from ansys.aedt.toolkits.antenna.backend.antenna_models.horn import PyramidalRidged
>>> import ansys.aedt.core
>>> app = ansys.aedt.core.Hfss()
>>> oantenna1 = PyramidalRidged(app)
>>> oantenna1.frequency = 12.0
>>> oantenna1.model_hfss()
>>> oantenna1.setup_hfss()
>>> oantenna2 = PyramidalRidged(app, origin=[0.2, 0.5, 0])
>>> oantenna2.model_hfss()
>>> oantenna2.setup_hfss()
>>> app.release_desktop(False, False)
"""
_default_input_parameters = {
"name": "",
"origin": [0, 0, 0],
"length_unit": None,
"coordinate_system": "Global",
"frequency": 10.0,
"frequency_unit": "GHz",
"material": "pec",
"outer_boundary": "",
}
def __init__(self, *args, **kwargs):
CommonHorn.__init__(self, self._default_input_parameters, *args, **kwargs)
self._parameters = self.synthesis()
self.update_synthesis_parameters(self._parameters)
self.antenna_type = "PyramidalRidged"
[docs]
@pyaedt_function_handler()
def synthesis(self):
"""Antenna synthesis.
Returns
-------
dict
Analytical parameters.
"""
parameters = {}
freq_ghz = constants.unit_converter(self.frequency, "Freq", self.frequency_unit, "GHz")
scale = lambda x: (1.0 / freq_ghz) * x
def scale_value(value, round_val=3, doScale=True):
if doScale:
value = scale(value)
return round(value, round_val)
aperture_height = scale_value(140.0)
aperture_width = scale_value(200.0)
flare_length = scale_value(160.0)
wall_thickness = scale_value(5.0)
wg_height = scale_value(28.4)
wg_width = scale_value(44.85)
wg_length = scale_value(15.6)
ridge_width = scale_value(14.64)
ridge_spacing = scale_value(2)
aperture_height = constants.unit_converter(aperture_height, "Length", "mm", self.length_unit)
parameters["aperture_height"] = aperture_height
aperture_width = constants.unit_converter(aperture_width, "Length", "mm", self.length_unit)
parameters["aperture_width"] = aperture_width
flare_length = constants.unit_converter(flare_length, "Length", "mm", self.length_unit)
parameters["flare_length"] = flare_length
wall_thickness = constants.unit_converter(wall_thickness, "Length", "mm", self.length_unit)
parameters["wall_thickness"] = wall_thickness
wg_height = constants.unit_converter(wg_height, "Length", "mm", self.length_unit)
parameters["wg_height"] = wg_height
wg_width = constants.unit_converter(wg_width, "Length", "mm", self.length_unit)
parameters["wg_width"] = wg_width
wg_length = constants.unit_converter(wg_length, "Length", "mm", self.length_unit)
parameters["wg_length"] = wg_length
ridge_width = constants.unit_converter(ridge_width, "Length", "mm", self.length_unit)
parameters["ridge_width"] = ridge_width
ridge_spacing = constants.unit_converter(ridge_spacing, "Length", "mm", self.length_unit)
parameters["ridge_spacing"] = ridge_spacing
parameters["pos_x"] = self.origin[0]
parameters["pos_y"] = self.origin[1]
parameters["pos_z"] = self.origin[2]
myKeys = list(parameters.keys())
myKeys.sort()
parameters_out = OrderedDict([(i, parameters[i]) for i in myKeys])
return parameters_out
[docs]
@pyaedt_function_handler()
def model_hfss(self):
"""Draw conical horn antenna.
Once the antenna is created, this method is not used anymore."""
if self.object_list:
self._app.logger.warning("This antenna already exists.")
return False
if (
self.material not in self._app.materials.mat_names_aedt
and self.material not in self._app.materials.mat_names_aedt_lower
):
self._app.logger.warning("Material not found. Create the material before assigning it.")
return False
self.set_variables_in_hfss()
# Solution type: Modal
self._app.solution_type = "Modal"
# Map parameters
aperture_height = self.synthesis_parameters.aperture_height.hfss_variable
aperture_width = self.synthesis_parameters.aperture_width.hfss_variable
flare_length = self.synthesis_parameters.flare_length.hfss_variable
wall_thickness = self.synthesis_parameters.wall_thickness.hfss_variable
wg_height = self.synthesis_parameters.wg_height.hfss_variable
wg_width = self.synthesis_parameters.wg_width.hfss_variable
wg_length = self.synthesis_parameters.wg_length.hfss_variable
ridge_width = self.synthesis_parameters.ridge_width.hfss_variable
ridge_spacing = self.synthesis_parameters.ridge_spacing.hfss_variable
pos_x = self.synthesis_parameters.pos_x.hfss_variable
pos_y = self.synthesis_parameters.pos_y.hfss_variable
pos_z = self.synthesis_parameters.pos_z.hfss_variable
antenna_name = self.name
coordinate_system = self.coordinate_system
# Base of the horn
# Air
air = self._app.modeler.create_box(
origin=[
"-" + wg_width + "/2",
"-" + wg_height + "/2",
"-" + wg_length,
],
sizes=[wg_width, wg_height, wg_length],
material="vacuum",
)
air.history().props["Coordinate System"] = coordinate_system
# Wall
wall = self._app.modeler.create_box(
origin=[
"-" + wg_width + "/2" + "-" + wall_thickness,
"-" + wg_height + "/2" + "-" + wall_thickness,
"-" + wg_length,
],
sizes=[
wg_width + "+2*" + wall_thickness,
wg_height + "+2*" + wall_thickness,
wg_length,
],
name="wall_" + antenna_name,
material="vacuum",
)
wall.history().props["Coordinate System"] = coordinate_system
# Subtract
new_wall = self._app.modeler.subtract(tool_list=[air.name], blank_list=[wall.name], keep_originals=False)
# Top of the horn
# Input
wg_in = self._app.modeler.create_box(
origin=[
"-" + wg_width + "/2",
"-" + wg_height + "/2",
"-" + wg_length,
],
sizes=[wg_width, wg_height, wg_length],
name="wg_inner" + antenna_name,
material="vacuum",
)
wg_in.history().props["Coordinate System"] = coordinate_system
wg_in.color = (128, 255, 255)
# Cap
cap = self._app.modeler.create_box(
origin=[
"-" + wg_width + "/2" + "-" + wall_thickness,
"-" + wg_height + "/2" + "-" + wall_thickness,
"-" + wg_length,
],
sizes=[
wg_width + "+" + "2*" + wall_thickness,
wg_height + "+2*" + wall_thickness,
"-" + wall_thickness,
],
name="port_cap_" + antenna_name,
material="pec",
)
cap.history().props["Coordinate System"] = coordinate_system
cap.color = (132, 132, 193)
# P1
p1 = self._app.modeler.create_rectangle(
orientation=2,
origin=[
"-" + wg_width + "/2",
"-" + wg_height + "/2",
"-" + wg_length,
],
sizes=[wg_width, wg_height],
name="port_" + antenna_name,
)
p1.color = (128, 0, 0)
p1.history().props["Coordinate System"] = coordinate_system
# Horn wall
base = self._app.modeler.create_rectangle(
orientation=2,
origin=[
"-" + wg_width + "/2",
"-" + wg_height + "/2",
"0",
],
sizes=[wg_width, wg_height],
name="base_" + antenna_name,
)
base.history().props["Coordinate System"] = coordinate_system
base_wall = self._app.modeler.create_rectangle(
orientation=2,
origin=[
"-" + wg_width + "/2" + "-" + wall_thickness,
"-" + wg_height + "/2" + "-" + wall_thickness,
"0",
],
sizes=[
wg_width + "+" + "2*" + wall_thickness,
wg_height + "+2*" + wall_thickness,
],
name="base_wall_" + antenna_name,
)
base_wall.history().props["Coordinate System"] = coordinate_system
horn_top = self._app.modeler.create_rectangle(
orientation=2,
origin=[
"-" + aperture_width + "/2",
"-" + aperture_height + "/2",
flare_length,
],
sizes=[aperture_width, aperture_height],
name="horn_top_" + antenna_name,
)
horn_top.history().props["Coordinate System"] = coordinate_system
horn = self._app.modeler.create_rectangle(
orientation=2,
origin=[
"-" + aperture_width + "/2" + "-" + wall_thickness,
"-" + aperture_height + "/2" + "-" + wall_thickness,
flare_length,
],
sizes=[
aperture_width + "+" + "2*" + wall_thickness,
aperture_height + "+" + "2*" + wall_thickness,
],
name="horn_" + antenna_name,
)
horn.history().props["Coordinate System"] = coordinate_system
# Ridge
def ridge_position(sign="+"):
position = []
if sign == "+":
sign = ""
position.append(["0", sign + "(" + ridge_spacing + "/2)", "0"])
position.append(
[
"0",
sign
+ "("
+ ridge_spacing
+ "/2"
+ "+"
+ "("
+ aperture_height
+ "-"
+ ridge_spacing
+ ")/2*"
+ "0.00417)",
flare_length + "*1/8",
]
)
position.append(
[
"0",
sign
+ "("
+ ridge_spacing
+ "/2"
+ "+"
+ "("
+ aperture_height
+ "-"
+ ridge_spacing
+ ")/2*"
+ "0.0179)",
flare_length + "*2/8",
]
)
position.append(
[
"0",
sign
+ "("
+ ridge_spacing
+ "/2"
+ "+"
+ "("
+ aperture_height
+ "-"
+ ridge_spacing
+ ")/2*"
+ "0.0439)",
flare_length + "*3/8",
]
)
position.append(
[
"0",
sign
+ "("
+ ridge_spacing
+ "/2"
+ "+"
+ "("
+ aperture_height
+ "-"
+ ridge_spacing
+ ")/2*"
+ "0.0858)",
flare_length + "*4/8",
]
)
position.append(
[
"0",
sign
+ "("
+ ridge_spacing
+ "/2"
+ "+"
+ "("
+ aperture_height
+ "-"
+ ridge_spacing
+ ")/2*"
+ "0.1502)",
flare_length + "*5/8",
]
)
position.append(
[
"0",
sign
+ "("
+ ridge_spacing
+ "/2"
+ "+"
+ "("
+ aperture_height
+ "-"
+ ridge_spacing
+ ")/2*"
+ "0.1942)",
flare_length + "*11/16",
]
)
position.append(
[
"0",
sign
+ "("
+ ridge_spacing
+ "/2"
+ "+"
+ "("
+ aperture_height
+ "-"
+ ridge_spacing
+ ")/2*"
+ "0.25)",
flare_length + "*6/8",
]
)
position.append(
[
"0",
sign
+ "("
+ ridge_spacing
+ "/2"
+ "+"
+ "("
+ aperture_height
+ "-"
+ ridge_spacing
+ ")/2*"
+ "0.2945)",
flare_length + "*19/24",
]
)
position.append(
[
"0",
sign
+ "("
+ ridge_spacing
+ "/2"
+ "+"
+ "("
+ aperture_height
+ "-"
+ ridge_spacing
+ ")/2*"
+ "0.3486)",
flare_length + "*5/6",
]
)
position.append(
[
"0",
sign
+ "("
+ ridge_spacing
+ "/2"
+ "+"
+ "("
+ aperture_height
+ "-"
+ ridge_spacing
+ ")/2*"
+ "0.4183)",
flare_length + "*7/8",
]
)
position.append(
[
"0",
sign
+ "("
+ ridge_spacing
+ "/2"
+ "+"
+ "("
+ aperture_height
+ "-"
+ ridge_spacing
+ ")/2*"
+ "0.4776)",
flare_length + "*29/32",
]
)
position.append(
[
"0",
sign
+ "("
+ ridge_spacing
+ "/2"
+ "+"
+ "("
+ aperture_height
+ "-"
+ ridge_spacing
+ ")/2*"
+ "0.5549)",
flare_length + "*15/16",
]
)
position.append(
[
"0",
sign
+ "("
+ ridge_spacing
+ "/2"
+ "+"
+ "("
+ aperture_height
+ "-"
+ ridge_spacing
+ ")/2*"
+ "0.6780)",
flare_length + "*31/32",
]
)
position.append(
[
"0",
sign
+ "("
+ ridge_spacing
+ "/2"
+ "+"
+ "("
+ aperture_height
+ "-"
+ ridge_spacing
+ ")/2*"
+ "0.7654)",
flare_length + "*63/64",
]
)
position.append(
[
"0",
sign
+ "("
+ ridge_spacing
+ "/2"
+ "+"
+ "("
+ aperture_height
+ "-"
+ ridge_spacing
+ ")/2*"
+ "0.8627)",
flare_length + "*127/128",
]
)
position.append(["0", sign + aperture_height + "/2", flare_length])
position.append(["0", sign + wg_height + "/2", "0"])
return position
ridge = self._app.modeler.create_polyline(
position_list=ridge_position(),
cover_surface=True,
name="right_ridge" + antenna_name,
material=self.material,
)
ridge = self._app.modeler.thicken_sheet(ridge, ridge_width, True)
ridge.history().props["Coordinate System"] = coordinate_system
ridge.color = (132, 132, 193)
mridge = self._app.modeler.create_polyline(
position_list=ridge_position("-"),
cover_surface=True,
name="left_ridge" + antenna_name,
material=self.material,
)
mridge = self._app.modeler.thicken_sheet(mridge, ridge_width, True)
mridge.history().props["Coordinate System"] = coordinate_system
mridge.color = (132, 132, 193)
# Connectors of the ridge
# Connector
connector = self._app.modeler.create_box(
origin=[
"-" + ridge_width + "/2",
"-" + wg_height + "/2",
"-" + wg_length,
],
sizes=[
ridge_width,
"(" + wg_height + "-" + ridge_spacing + ")/2",
wg_length,
],
name="connector_" + antenna_name,
material="pec",
)
connector.history().props["Coordinate System"] = coordinate_system
connector.color = (132, 132, 193)
# Bottom connector
bconnector = self._app.modeler.create_box(
origin=[
"-" + ridge_width + "/2",
wg_height + "/2",
"-" + wg_length,
],
sizes=[
ridge_width,
"-(" + wg_height + "-" + ridge_spacing + ")/2",
wg_length,
],
name="bconnector_" + antenna_name,
material="pec",
)
bconnector.history().props["Coordinate System"] = coordinate_system
bconnector.color = (132, 132, 193)
# Connect pieces
self._app.modeler.connect([horn.name, base_wall.name])
self._app.modeler.connect([base.name, horn_top.name])
self._app.modeler.subtract(horn.name, base.name, False)
self._app.modeler.unite([horn, wall, ridge, mridge, connector, bconnector])
horn.color = (255, 128, 65)
horn.material_name = self.material
# Air base
air_base = self._app.modeler.create_rectangle(
orientation=2,
origin=[
"-" + wg_width + "/2",
"-" + wg_height + "/2",
"0",
],
sizes=[
wg_width,
wg_height,
],
name="air_base_" + antenna_name,
)
air_base.history().props["Coordinate System"] = coordinate_system
# Air top
air_top = self._app.modeler.create_rectangle(
orientation=2,
origin=[
"-" + aperture_width + "/2",
"-" + aperture_height + "/2",
flare_length,
],
sizes=[
aperture_width,
aperture_height,
],
name="air_top_" + antenna_name,
)
air_top.history().props["Coordinate System"] = coordinate_system
self._app.modeler.connect([air_base.name, air_top.name])
self._app.modeler.unite([wg_in, air_base])
self.object_list[cap.name] = cap
self.object_list[horn.name] = horn
self.object_list[wg_in.name] = wg_in
self.object_list[p1.name] = p1
self._app.modeler.move([cap, horn, wg_in, p1], [pos_x, pos_y, pos_z])
self._app.change_material_override(True)
cap.group_name = antenna_name
horn.group_name = antenna_name
wg_in.group_name = antenna_name
p1.group_name = antenna_name
[docs]
@pyaedt_function_handler()
def model_disco(self):
"""Model in PyDiscovery. To be implemented."""
pass
[docs]
@pyaedt_function_handler()
def setup_disco(self):
"""Set up model in PyDiscovery. To be implemented."""
pass
[docs]
class Corrugated(CommonHorn):
"""Manages a corrugated horn antenna.
This class is accessible through the app hfss object [1]_.
Parameters
----------
frequency : float, optional
Center frequency. The default is ``10.0``.
frequency_unit : str, optional
Frequency units. The default is ``"GHz"``.
material : str, optional
Horn material. If a material is not defined, a new material, ``parametrized``, is defined.
The default is ``"pec"``.
outer_boundary : str, optional
Boundary type to use. The default is ``None``. Options are ``"FEBI"``, ``"PML"``,
``"Radiation"``, and ``None``.
length_unit : str, optional
Length units. The default is ``"mm"``.
parametrized : bool, optional
Whether to create a parametrized antenna. The default is ``True``.
Returns
-------
:class:`aedt.toolkits.antenna.CorrugatedHorn`
Corrugated horn object.
Notes
-----
.. [1] C. Balanis, "Horn Antennas," Antenna Theory Analysis,
3rd ed. Hoboken: Wiley, 2005, sec. 13.6, pp. 785-791.
Examples
--------
>>> from ansys.aedt.toolkits.antenna.backend.antenna_models.horn import Corrugated
>>> import ansys.aedt.core
>>> app = ansys.aedt.core.Hfss()
>>> oantenna1 = Corrugated(app)
>>> oantenna1.frequency = 12.0
>>> oantenna1.model_hfss()
>>> oantenna1.setup_hfss()
>>> app.release_desktop(False, False)
"""
_default_input_parameters = {
"name": "",
"origin": [0, 0, 0],
"length_unit": "meter",
"coordinate_system": "Global",
"frequency": 10.0,
"frequency_unit": "GHz",
"material": "pec",
"outer_boundary": "",
}
def __init__(self, *args, **kwargs):
CommonHorn.__init__(self, self._default_input_parameters, *args, **kwargs)
self._parameters = self.synthesis()
self.update_synthesis_parameters(self._parameters)
self.antenna_type = "Corrugated"
[docs]
@pyaedt_function_handler()
def synthesis(self):
"""Antenna synthesis.
Returns
-------
dict
Analytical parameters.
"""
parameters = {}
freq_ghz = constants.unit_converter(self.frequency, "Freq", self.frequency_unit, "GHz")
wg_radius_mm = round(11.7 * 10.4 / freq_ghz, 3)
wg_length_mm = round(30.0 * 10.4 / freq_ghz, 3)
wall_thickness_mm = round(2.0 * 10.4 / freq_ghz, 3)
flare_angle = 20
notches = 25.0
notch_width_mm = round(2.0 * 10.4 / freq_ghz, 3)
notch_depth_mm = round(7.5 * 10.4 / freq_ghz, 3)
tooth_width_mm = round(2.0 * 10.4 / freq_ghz, 3)
wg_radius = constants.unit_converter(wg_radius_mm, "Length", "mm", self.length_unit)
parameters["wg_radius"] = wg_radius
wg_length = constants.unit_converter(wg_length_mm, "Length", "mm", self.length_unit)
parameters["wg_length"] = wg_length
wall_thickness = constants.unit_converter(wall_thickness_mm, "Length", "mm", self.length_unit)
parameters["wall_thickness"] = wall_thickness
parameters["flare_angle"] = flare_angle
parameters["notches"] = notches
notch_width = constants.unit_converter(notch_width_mm, "Length", "mm", self.length_unit)
parameters["notch_width"] = notch_width
notch_depth = constants.unit_converter(notch_depth_mm, "Length", "mm", self.length_unit)
parameters["notch_depth"] = notch_depth
tooth_width = constants.unit_converter(tooth_width_mm, "Length", "mm", self.length_unit)
parameters["tooth_width"] = tooth_width
parameters["pos_x"] = self.origin[0]
parameters["pos_y"] = self.origin[1]
parameters["pos_z"] = self.origin[2]
myKeys = list(parameters.keys())
myKeys.sort()
parameters_out = OrderedDict([(i, parameters[i]) for i in myKeys])
return parameters_out
[docs]
@pyaedt_function_handler()
def model_hfss(self):
"""Draw a conical horn antenna.
Once the antenna is created, this method is not used anymore."""
if self.object_list:
logger.debug("This antenna already exists")
return False
if (
self.material not in self._app.materials.mat_names_aedt
and self.material not in self._app.materials.mat_names_aedt_lower
):
self._app.logger.warning("Material not found. Create the material before assigning it.")
return False
# Not used parameters in HFSS
notches = self.synthesis_parameters.notches.hfss_variable
notches_value = self.synthesis_parameters.notches.value
del self.synthesis_parameters.notches
# Solution type: Modal
self._app.solution_type = "Modal"
self.set_variables_in_hfss([notches])
# Map parameters
wall_thickness = self.synthesis_parameters.wall_thickness.hfss_variable
wg_length = self.synthesis_parameters.wg_length.hfss_variable
wg_radius = self.synthesis_parameters.wg_radius.hfss_variable
self._app[self.synthesis_parameters.flare_angle.hfss_variable] = (
str(self.synthesis_parameters.flare_angle.value) + "deg"
)
flare_angle = self.synthesis_parameters.flare_angle.hfss_variable
notch_width = self.synthesis_parameters.notch_width.hfss_variable
notch_depth = self.synthesis_parameters.notch_depth.hfss_variable
tooth_width = self.synthesis_parameters.tooth_width.hfss_variable
pos_x = self.synthesis_parameters.pos_x.hfss_variable
pos_y = self.synthesis_parameters.pos_y.hfss_variable
pos_z = self.synthesis_parameters.pos_z.hfss_variable
antenna_name = self.name
coordinate_system = self.coordinate_system
l = self._app.variable_manager[wg_length].numeric_value
n = notches_value
Ka = "tan(" + flare_angle + ")"
# Based on inputs calculate minimum feed length for geometry to work,
# and loop until user inputs value above minimum required.
pts = []
zStart = "0.0"
pts.append([wg_radius, "0.0", "0.0"])
if l > 0.0:
zStart = wg_length
pts.append([wg_radius, 0, zStart])
count = 1
N = 1
while count <= n:
# Create constants K1 through K3, used in coordinate calculations.
K1 = str((N - 1)) + "*" + "(" + notch_width + "+" + tooth_width + ")"
K2 = "(" + str(N) + "*" + notch_width + ")+(" + str(N - 1) + ")*" + tooth_width
K3 = str(N) + "*" + "(" + notch_width + "+" + tooth_width + ")"
xdel1 = "(" + K1 + ")*" + Ka
xdel2 = "(" + K2 + ")*" + Ka
xdel3 = "(" + K3 + ")*" + Ka
c1 = K1
c2 = K2
c3 = K3
del1 = xdel1
del2 = xdel2
del3 = xdel3
# Create individual components of necessary points
c1x = wg_radius + "+" + notch_depth + "+" + del1
c1z = zStart + "+" + c1
c2x = wg_radius + "+" + notch_depth + "+" + del2
c2z = zStart + "+" + c2
c3x = wg_radius + "+" + del2
c3z = zStart + "+" + c2
c4x = wg_radius + "+" + del3
c4z = zStart + "+" + c3
# Begin drawing corrugations
pts.append([c1x, 0, c1z])
pts.append([c2x, 0, c2z])
pts.append([c3x, 0, c3z])
pts.append([c4x, 0, c4z])
count2 = count + 1
count = count2
N = count
# Draw end of horn and exterior outline.
# This calculation is what required the minimum feed length test,
# or calculated x-axis point for exterior could end up BEHIND port plane.
temp1 = c4x + "+" + wall_thickness
endx = temp1 + "+" + notch_depth
pts.append([endx, 0, c4z])
out1 = endx
out2 = wg_radius + "+" + wall_thickness
out3 = c4z
zpart = out3 + "-" + "(((" + out1 + ")-(" + out2 + ")) /(" + Ka + "))"
finx = out2
finz = zpart
pts.append([finx, 0, finz])
pts.append([finx, 0, 0])
pts.append([pts[0][0], pts[0][1], pts[0][2]])
horn = self._app.modeler.create_polyline(
position_list=pts,
cover_surface=True,
name="horn" + antenna_name,
material=self.material,
)
horn = horn.sweep_around_axis(2)
horn.history().props["Coordinate System"] = coordinate_system
horn.color = (132, 132, 193)
# Cap
cap = self._app.modeler.create_cylinder(
orientation=2,
origin=["0", "0", "0"],
radius=wg_radius + "+" + wall_thickness,
height="-" + wall_thickness,
name="port_cap_" + antenna_name,
material="pec",
)
cap.history().props["Coordinate System"] = coordinate_system
# P1
p1 = self._app.modeler.create_circle(
cs_plane=2,
origin=["0", "0", "0"],
radius=wg_radius,
name="port_" + antenna_name,
)
p1.color = (128, 0, 0)
p1.history().props["Coordinate System"] = coordinate_system
self.object_list[horn.name] = horn
self.object_list[cap.name] = cap
self.object_list[p1.name] = p1
self._app.modeler.move(list(self.object_list.keys()), [pos_x, pos_y, pos_z])
horn.group_name = antenna_name
cap.group_name = antenna_name
p1.group_name = antenna_name
[docs]
@pyaedt_function_handler()
def model_disco(self):
"""Model in PyDiscovery. To be implemented."""
pass
[docs]
@pyaedt_function_handler()
def setup_disco(self):
"""Set up in PyDiscovery. To be implemented."""
pass
[docs]
class Elliptical(CommonHorn):
"""Manages an elliptical horn antenna.
This class is accessible through the app hfss object [1]_.
Parameters
----------
frequency : float, optional
Center frequency. The default is ``10.0``.
frequency_unit : str, optional
Frequency units. The default is ``"GHz"``.
material : str, optional
Horn material. If a material is not defined, a new material, ``parametrized``, is defined.
The default is ``"pec"``.
outer_boundary : str, optional
Boundary type to use. The default is ``None``. Options are ``"FEBI"``, ``"PML"``,
``"Radiation"``, and ``None``.
length_unit : str, optional
Length units. The default is ``"mm"``.
parametrized : bool, optional
Whether to create a parametrized antenna. The default is ``True``.
Returns
-------
:class:`aedt.toolkits.antenna.EllipticalHorn`
Elliptical horn object.
Notes
-----
.. [1] C. Balanis, "Aperture Antennas: Analysis, Design, and Applications,"
*Modern Antenna Handbook*, New York, 2008.
Examples
--------
>>> from ansys.aedt.toolkits.antenna.backend.antenna_models.horn import PyramidalRidged
>>> import ansys.aedt.core
>>> app = ansys.aedt.core.Hfss()
>>> oantenna1 = Elliptical(app)
>>> oantenna1.frequency = 12.0
>>> oantenna1.model_hfss()
>>> oantenna1.setup_hfss()
>>> oantenna2 = Elliptical(app, origin=[0.2, 0.5, 0])
>>> oantenna2.model_hfss()
>>> oantenna2.setup_hfss()
>>> app.release_desktop(False, False)
"""
_default_input_parameters = {
"name": None,
"origin": [0, 0, 0],
"length_unit": None,
"coordinate_system": "Global",
"frequency": 10.0,
"frequency_unit": "GHz",
"material": "pec",
"outer_boundary": None,
}
def __init__(self, *args, **kwargs):
CommonHorn.__init__(self, self._default_input_parameters, *args, **kwargs)
self._parameters = self.synthesis()
self.update_synthesis_parameters(self._parameters)
self.antenna_type = "Elliptical"
[docs]
@pyaedt_function_handler()
def synthesis(self):
"""Antenna synthesis.
Returns
-------
dict
Analytical parameters.
"""
parameters = {}
lightSpeed = constants.SpeedOfLight # m/s
freq_hz = constants.unit_converter(self.frequency, "Freq", self.frequency_unit, "Hz")
wavelength = lightSpeed / freq_hz
wavelength_in = constants.unit_converter(wavelength, "Length", "meter", "in")
wg_radius_in = 0.5 * wavelength_in
wg_length_in = wavelength_in
horn_radius_in = 1.4 * wavelength_in
horn_length_in = 2 * wavelength_in
wall_thickness_in = 0.02 * wavelength_in
ellipse_ratio = 0.6
wg_radius = constants.unit_converter(wg_radius_in, "Length", "in", self.length_unit)
parameters["wg_radius"] = wg_radius
wg_length = constants.unit_converter(wg_length_in, "Length", "in", self.length_unit)
parameters["wg_length"] = wg_length
horn_radius = constants.unit_converter(horn_radius_in, "Length", "in", self.length_unit)
parameters["horn_radius"] = horn_radius
horn_length = constants.unit_converter(horn_length_in, "Length", "in", self.length_unit)
parameters["horn_length"] = horn_length
wall_thickness = constants.unit_converter(wall_thickness_in, "Length", "in", self.length_unit)
parameters["wall_thickness"] = wall_thickness
parameters["ellipse_ratio"] = ellipse_ratio
parameters["pos_x"] = self.origin[0]
parameters["pos_y"] = self.origin[1]
parameters["pos_z"] = self.origin[2]
myKeys = list(parameters.keys())
myKeys.sort()
parameters_out = OrderedDict([(i, parameters[i]) for i in myKeys])
return parameters_out
[docs]
@pyaedt_function_handler()
def model_hfss(self):
"""Draw elliptical horn antenna.
Once the antenna is created, this method is not used anymore."""
if self.object_list:
self._app.logger.warning("This antenna already exists.")
return False
if (
self.material not in self._app.materials.mat_names_aedt
and self.material not in self._app.materials.mat_names_aedt_lower
):
self._app.logger.warning("Material not found. Create the material before assigning it.")
return False
self.set_variables_in_hfss()
# Solution type: Modal
self._app.solution_type = "Modal"
# Map parameters
horn_length = self.synthesis_parameters.horn_length.hfss_variable
horn_radius = self.synthesis_parameters.horn_radius.hfss_variable
wall_thickness = self.synthesis_parameters.wall_thickness.hfss_variable
wg_length = self.synthesis_parameters.wg_length.hfss_variable
wg_radius = self.synthesis_parameters.wg_radius.hfss_variable
ellipse_ratio = self.synthesis_parameters.ellipse_ratio.hfss_variable
pos_x = self.synthesis_parameters.pos_x.hfss_variable
pos_y = self.synthesis_parameters.pos_y.hfss_variable
pos_z = self.synthesis_parameters.pos_z.hfss_variable
antenna_name = self.name
coordinate_system = self.coordinate_system
# Negative air
neg_air = self._app.modeler.create_cylinder(
orientation=2,
origin=["0", "0", "0"],
radius=wg_radius,
height="-" + wg_length,
material="vacuum",
)
neg_air.history().props["Coordinate System"] = coordinate_system
# Wall
wall = self._app.modeler.create_cylinder(
orientation=2,
origin=["0", "0", "0"],
radius=wg_radius + "+" + wall_thickness,
height="-" + wg_length,
name="wg_outer_" + antenna_name,
material=self.material,
)
wall.history().props["Coordinate System"] = coordinate_system
# Subtract
new_wall = self._app.modeler.subtract(tool_list=[neg_air.name], blank_list=[wall.name], keep_originals=False)
# Input
wg_in = self._app.modeler.create_cylinder(
orientation=2,
origin=["0", "0", "0"],
radius=wg_radius,
height="-" + wg_length,
name="wg_inner_" + antenna_name,
material="vacuum",
)
wg_in.history().props["Coordinate System"] = coordinate_system
# Cap
cap = self._app.modeler.create_cylinder(
orientation=2,
origin=["0", "0", "-" + wg_length],
radius=wg_radius + "+" + wall_thickness,
height="-" + wall_thickness,
name="port_cap_" + antenna_name,
material="pec",
)
cap.history().props["Coordinate System"] = coordinate_system
# P1
p1 = self._app.modeler.create_circle(
cs_plane=2,
origin=["0", "0", "-" + wg_length],
radius=wg_radius,
name="port_" + antenna_name,
)
p1.color = (128, 0, 0)
p1.history().props["Coordinate System"] = coordinate_system
# Horn wall
base = self._app.modeler.create_circle(
cs_plane=2,
origin=["0", "0", "0"],
radius=wg_radius,
)
base.history().props["Coordinate System"] = coordinate_system
base_wall = self._app.modeler.create_circle(
cs_plane=2,
origin=["0", "0", "0"],
radius=wg_radius + "+" + wall_thickness,
)
base_wall.history().props["Coordinate System"] = coordinate_system
horn_top = self._app.modeler.create_ellipse(
cs_plane=2,
origin=["0", "0", horn_length],
major_radius=horn_radius,
ratio=ellipse_ratio,
)
horn_top.history().props["Coordinate System"] = coordinate_system
horn_sheet = self._app.modeler.create_ellipse(
cs_plane=2,
origin=["0", "0", horn_length],
major_radius=horn_radius + "+" + wall_thickness,
ratio=ellipse_ratio,
)
horn_sheet.history().props["Coordinate System"] = coordinate_system
self._app.modeler.connect([horn_sheet.name, base_wall.name])
self._app.modeler.connect([base.name, horn_top.name])
# Horn
self._app.modeler.subtract(blank_list=[horn_sheet.name], tool_list=[base.name], keep_originals=False)
self._app.modeler.unite([horn_sheet.name, wall.name])
air_base = self._app.modeler.create_circle(
cs_plane=2,
origin=["0", "0", "0"],
radius=wg_radius,
)
air_base.history().props["Coordinate System"] = coordinate_system
air_top = self._app.modeler.create_ellipse(
cs_plane=2,
origin=["0", "0", horn_length],
major_radius=horn_radius,
ratio=ellipse_ratio,
)
self._app.modeler.connect([air_base, air_top])
self._app.modeler.unite([wg_in, air_base])
wg_in.name = "internal_" + antenna_name
wg_in.color = (128, 255, 255)
horn_sheet.name = "metal_" + antenna_name
horn_sheet.material_name = self.material
horn_sheet.color = (255, 128, 65)
cap.color = (132, 132, 192)
p1.color = (128, 0, 0)
self.object_list[wg_in.name] = wg_in
self.object_list[horn_sheet.name] = horn_sheet
self.object_list[cap.name] = cap
self.object_list[p1.name] = p1
self._app.modeler.move(list(self.object_list.keys()), [pos_x, pos_y, pos_z])
wg_in.group_name = antenna_name
horn_sheet.group_name = antenna_name
cap.group_name = antenna_name
p1.group_name = antenna_name
[docs]
@pyaedt_function_handler()
def model_disco(self):
"""Model in PyDiscovery. To be implemented."""
pass
[docs]
@pyaedt_function_handler()
def setup_disco(self):
"""Set up in PyDiscovery. To be implemented."""
pass
[docs]
class EPlane(CommonHorn):
"""Manages an E plane horn antenna.
This class is accessible through the app hfss object [1]_.
Parameters
----------
frequency : float, optional
Center frequency. The default is ``10.0``.
frequency_unit : str, optional
Frequency units. The default is ``"GHz"``.
material : str, optional
Horn material. If a material is not defined, a new material, ``parametrized``, is defined.
The default is ``"pec"``.
outer_boundary : str, optional
Boundary type to use. The default is ``None``. Options are ``"FEBI"``, ``"PML"``,
``"Radiation"``, and ``None``.
length_unit : str, optional
Length units. The default is ``"mm"``.
parametrized : bool, optional
Whether to create a parametrized antenna. The default is ``True``.
Returns
-------
:class:`aedt.toolkits.antenna.EPlaneHorn`
E plane horn object.
Notes
-----
.. [1] C. Balanis, "Aperture Antennas: Analysis, Design, and Applications,"
*Modern Antenna Handbook*, New York, 2008.
Examples
--------
>>> from ansys.aedt.toolkits.antenna.backend.antenna_models.horn import EPlane
>>> import ansys.aedt.core
>>> app = ansys.aedt.core.Hfss()
>>> oantenna1 = EPlane(app)
>>> oantenna1.frequency = 12.0
>>> oantenna1.model_hfss()
>>> oantenna1.setup_hfss()
>>> oantenna2 = EPlane(app, origin=[0.2, 0.5, 0])
>>> oantenna2.model_hfss()
>>> oantenna2.setup_hfss()
>>> app.release_desktop(False, False)
"""
_default_input_parameters = {
"name": None,
"origin": [0, 0, 0],
"length_unit": None,
"coordinate_system": "Global",
"frequency": 10.0,
"frequency_unit": "GHz",
"material": "pec",
"material_properties": {},
"outer_boundary": None,
}
def __init__(self, *args, **kwargs):
CommonHorn.__init__(self, self._default_input_parameters, *args, **kwargs)
self._parameters = self.synthesis()
self.update_synthesis_parameters(self._parameters)
self.antenna_type = "EPlane"
[docs]
@pyaedt_function_handler()
def synthesis(self):
"""Antenna synthesis.
Returns
-------
dict
Analytical parameters.
"""
parameters = {}
freq_ghz = constants.unit_converter(self.frequency, "Freq", self.frequency_unit, "GHz")
if self._app and (
self.material in self._app.materials.mat_names_aedt
or self.material in self._app.materials.mat_names_aedt_lower
):
mat_props = self._app.materials[self.material]
permittivity = mat_props.permittivity.value
self._input_parameters.material_properties["permittivity"] = permittivity
elif isinstance(self.material_properties, dict):
pass
else:
self._app.logger.warning("Material not found. Create the material before assigning it.")
return parameters
scale = lambda x: (10.0 / freq_ghz) * x
def scale_value(value, round_val=3, doScale=True):
if doScale:
value = scale(value)
return round(value, round_val)
wg_length_in = scale_value(1.0)
flare_in = scale_value(1.4)
horn_length_in = scale_value(3.0)
wg_obj = StandardWaveguide()
wg_name = wg_obj.find_waveguide(freq_ghz)
if wg_name:
wg_dim_in = wg_obj.get_waveguide_dimensions(wg_name, self.length_unit)
wg_a = wg_dim_in[0]
wg_b = wg_dim_in[1]
wall_thickness = wg_dim_in[2]
else:
wg_a_in = scale_value(0.9)
wg_a = constants.unit_converter(wg_a_in, "Length", "in", self.length_unit)
wg_b_in = scale_value(0.4)
wg_b = constants.unit_converter(wg_b_in, "Length", "in", self.length_unit)
wall_thickness_in = scale_value(0.02)
wall_thickness = constants.unit_converter(wall_thickness_in, "Length", "in", self.length_unit)
wg_length = constants.unit_converter(wg_length_in, "Length", "in", self.length_unit)
parameters["wg_length"] = wg_length
flare = constants.unit_converter(flare_in, "Length", "in", self.length_unit)
parameters["flare"] = flare
horn_length = constants.unit_converter(horn_length_in, "Length", "in", self.length_unit)
parameters["horn_length"] = horn_length
parameters["wg_width"] = wg_a
parameters["wg_height"] = wg_b
parameters["wall_thickness"] = wall_thickness
parameters["pos_x"] = self.origin[0]
parameters["pos_y"] = self.origin[1]
parameters["pos_z"] = self.origin[2]
myKeys = list(parameters.keys())
myKeys.sort()
parameters_out = OrderedDict([(i, parameters[i]) for i in myKeys])
return parameters_out
[docs]
@pyaedt_function_handler()
def model_hfss(self):
"""Draw E plane horn antenna.
Once the antenna is created, this method is not used anymore."""
if self.object_list:
self._app.logger.warning("This antenna already exists.")
return False
if (
self.material not in self._app.materials.mat_names_aedt
and self.material not in self._app.materials.mat_names_aedt_lower
):
self._app.logger.warning("Material not found. Create the material before assigning it.")
return False
self.set_variables_in_hfss()
# Solution type: Modal
self._app.solution_type = "Modal"
# Map parameters
wg_length = self.synthesis_parameters.wg_length.hfss_variable
flare = self.synthesis_parameters.flare.hfss_variable
horn_length = self.synthesis_parameters.horn_length.hfss_variable
wg_width = self.synthesis_parameters.wg_width.hfss_variable
wg_height = self.synthesis_parameters.wg_height.hfss_variable
wall_thickness = self.synthesis_parameters.wall_thickness.hfss_variable
pos_x = self.synthesis_parameters.pos_x.hfss_variable
pos_y = self.synthesis_parameters.pos_y.hfss_variable
pos_z = self.synthesis_parameters.pos_z.hfss_variable
antenna_name = self.name
coordinate_system = self.coordinate_system
# Base of the horn
# Air
air = self._app.modeler.create_box(
origin=[
"-" + wg_width + "/2",
"-" + wg_height + "/2",
"-" + wg_length,
],
sizes=[wg_width, wg_height, wg_length],
material="vacuum",
)
air.history().props["Coordinate System"] = coordinate_system
# Wall
wall = self._app.modeler.create_box(
origin=[
"-" + wg_width + "/2" + "-" + wall_thickness,
"-" + wg_height + "/2" + "-" + wall_thickness,
"-" + wg_length,
],
sizes=[
wg_width + "+2*" + wall_thickness,
wg_height + "+2*" + wall_thickness,
wg_length,
],
name="wall_" + antenna_name,
material="vacuum",
)
wall.history().props["Coordinate System"] = coordinate_system
# Subtract
new_wall = self._app.modeler.subtract(tool_list=[air.name], blank_list=[wall.name], keep_originals=False)
# Top of the horn
# Input
wg_in = self._app.modeler.create_box(
origin=[
"-" + wg_width + "/2",
"-" + wg_height + "/2",
"-" + wg_length,
],
sizes=[wg_width, wg_height, wg_length],
name="wg_inner" + antenna_name,
material="vacuum",
)
wg_in.history().props["Coordinate System"] = coordinate_system
wg_in.color = (128, 255, 255)
# Cap
cap = self._app.modeler.create_box(
origin=[
"-" + wg_width + "/2" + "-" + wall_thickness,
"-" + wg_height + "/2" + "-" + wall_thickness,
"-" + wg_length,
],
sizes=[
wg_width + "+" + "2*" + wall_thickness,
wg_height + "+2*" + wall_thickness,
"-" + wall_thickness,
],
name="port_cap_" + antenna_name,
material="pec",
)
cap.history().props["Coordinate System"] = coordinate_system
cap.color = (132, 132, 193)
# P1
p1 = self._app.modeler.create_rectangle(
orientation=2,
origin=[
"-" + wg_width + "/2",
"-" + wg_height + "/2",
"-" + wg_length,
],
sizes=[wg_width, wg_height],
name="port_" + antenna_name,
)
p1.color = (128, 0, 0)
p1.history().props["Coordinate System"] = coordinate_system
# Horn wall
base = self._app.modeler.create_rectangle(
orientation=2,
origin=[
"-" + wg_width + "/2",
"-" + wg_height + "/2",
"0",
],
sizes=[wg_width, wg_height],
name="base_" + antenna_name,
)
base.history().props["Coordinate System"] = coordinate_system
base_wall = self._app.modeler.create_rectangle(
orientation=2,
origin=[
"-" + wg_width + "/2" + "-" + wall_thickness,
"-" + wg_height + "/2" + "-" + wall_thickness,
"0",
],
sizes=[
wg_width + "+" + "2*" + wall_thickness,
wg_height + "+2*" + wall_thickness,
],
name="base_wall_" + antenna_name,
)
base_wall.history().props["Coordinate System"] = coordinate_system
horn_top = self._app.modeler.create_rectangle(
orientation=2,
origin=[
"-" + wg_width + "/2",
"-" + flare + "/2",
horn_length,
],
sizes=[wg_width, flare],
name="horn_top_" + antenna_name,
)
horn_top.history().props["Coordinate System"] = coordinate_system
horn = self._app.modeler.create_rectangle(
orientation=2,
origin=[
"-" + wg_width + "/2" + "-" + wall_thickness,
"-" + flare + "/2" + "-" + wall_thickness,
horn_length,
],
sizes=[
wg_width + "+" + "2*" + wall_thickness,
flare + "+" + "2*" + wall_thickness,
],
name="horn_" + antenna_name,
)
horn.history().props["Coordinate System"] = coordinate_system
self._app.modeler.connect([horn, base_wall])
self._app.modeler.connect([base, horn_top])
new_wall = self._app.modeler.subtract(tool_list=[base.name], blank_list=[horn.name], keep_originals=False)
new_horn = self._app.modeler.unite([horn.name, wall.name])
horn.color = (132, 132, 193)
horn.material_name = self.material
# Air base
air_base = self._app.modeler.create_rectangle(
orientation=2,
origin=[
"-" + wg_width + "/2",
"-" + wg_height + "/2",
"0",
],
sizes=[
wg_width,
wg_height,
],
name="air_base_" + antenna_name,
)
air_base.history().props["Coordinate System"] = coordinate_system
# Air top
air_top = self._app.modeler.create_rectangle(
orientation=2,
origin=[
"-" + wg_width + "/2",
"-" + flare + "/2",
horn_length,
],
sizes=[
wg_width,
flare,
],
name="air_top_" + antenna_name,
)
air_top.history().props["Coordinate System"] = coordinate_system
self._app.modeler.connect([air_base.name, air_top.name])
self._app.modeler.unite([wg_in, air_base])
self.object_list[cap.name] = cap
self.object_list[horn.name] = horn
self.object_list[wg_in.name] = wg_in
self.object_list[p1.name] = p1
self._app.modeler.move([cap, horn, wg_in, p1], [pos_x, pos_y, pos_z])
cap.group_name = antenna_name
horn.group_name = antenna_name
wg_in.group_name = antenna_name
p1.group_name = antenna_name
[docs]
@pyaedt_function_handler()
def model_disco(self):
"""Model in PyDiscovery. To be implemented."""
pass
[docs]
@pyaedt_function_handler()
def setup_disco(self):
"""Set up model in PyDiscovery. To be implemented."""
pass
[docs]
class HPlane(CommonHorn):
"""Manages an H plane horn antenna.
This class is accessible through the app hfss object [1]_.
Parameters
----------
frequency : float, optional
Center frequency. The default is ``10.0``.
frequency_unit : str, optional
Frequency units. The default is ``"GHz"``.
material : str, optional
Horn material. If a material is not defined, a new material, ``parametrized``, is defined.
The default is ``"pec"``.
outer_boundary : str, optional
Boundary type to use. The default is ``None``. Options are ``"FEBI"``, ``"PML"``,
``"Radiation"``, and ``None``.
length_unit : str, optional
Length units. The default is ``"mm"``.
parametrized : bool, optional
Whether to create a parametrized antenna. The default is ``True``.
Returns
-------
:class:`aedt.toolkits.antenna.HPlaneHorn`
H plane horn object.
Notes
-----
.. [1] C. Balanis, "Aperture Antennas: Analysis, Design, and Applications,"
*Modern Antenna Handbook*, New York, 2008.
Examples
--------
>>> from ansys.aedt.toolkits.antenna.backend.antenna_models.horn import HPlane
>>> import ansys.aedt.core
>>> app = ansys.aedt.core.Hfss()
>>> oantenna1 = HPlane(app)
>>> oantenna1.frequency = 12.0
>>> oantenna1.model_hfss()
>>> oantenna1.setup_hfss()
>>> oantenna2 = HPlane(app, origin=[0.2, 0.5, 0])
>>> oantenna2.model_hfss()
>>> oantenna2.setup_hfss()
>>> app.release_desktop(False, False)
"""
_default_input_parameters = {
"name": None,
"origin": [0, 0, 0],
"length_unit": None,
"coordinate_system": "Global",
"frequency": 10.0,
"frequency_unit": "GHz",
"material": "pec",
"outer_boundary": None,
}
def __init__(self, *args, **kwargs):
CommonHorn.__init__(self, self._default_input_parameters, *args, **kwargs)
self._parameters = self.synthesis()
self.update_synthesis_parameters(self._parameters)
self.antenna_type = "HPlane"
[docs]
@pyaedt_function_handler()
def synthesis(self):
"""Antenna synthesis.
Returns
-------
dict
Analytical parameters.
"""
parameters = {}
freq_ghz = constants.unit_converter(self.frequency, "Freq", self.frequency_unit, "GHz")
scale = lambda x: (10.0 / freq_ghz) * x
def scale_value(value, round_val=3, doScale=True):
if doScale:
value = scale(value)
return round(value, round_val)
wg_length_in = scale_value(2.0)
flare_in = scale_value(1.8)
horn_length_in = scale_value(3.0)
wg_obj = StandardWaveguide()
wg_name = wg_obj.find_waveguide(freq_ghz)
if wg_name:
wg_dim_in = wg_obj.get_waveguide_dimensions(wg_name, self.length_unit)
wg_a = wg_dim_in[0]
wg_b = wg_dim_in[1]
wall_thickness = wg_dim_in[2]
else:
wg_a_in = scale_value(0.9)
wg_a = constants.unit_converter(wg_a_in, "Length", "in", self.length_unit)
wg_b_in = scale_value(0.4)
wg_b = constants.unit_converter(wg_b_in, "Length", "in", self.length_unit)
wall_thickness_in = scale_value(0.02)
wall_thickness = constants.unit_converter(wall_thickness_in, "Length", "in", self.length_unit)
wg_length = constants.unit_converter(wg_length_in, "Length", "in", self.length_unit)
parameters["wg_length"] = wg_length
flare = constants.unit_converter(flare_in, "Length", "in", self.length_unit)
parameters["flare"] = flare
horn_length = constants.unit_converter(horn_length_in, "Length", "in", self.length_unit)
parameters["horn_length"] = horn_length
parameters["wg_width"] = wg_a
parameters["wg_height"] = wg_b
parameters["wall_thickness"] = wall_thickness
parameters["pos_x"] = self.origin[0]
parameters["pos_y"] = self.origin[1]
parameters["pos_z"] = self.origin[2]
myKeys = list(parameters.keys())
myKeys.sort()
parameters_out = OrderedDict([(i, parameters[i]) for i in myKeys])
return parameters_out
[docs]
@pyaedt_function_handler()
def model_hfss(self):
"""Draw H plane horn antenna.
Once the antenna is created, this method is not used anymore."""
if self.object_list:
self._app.logger.warning("This antenna already exists.")
return False
if (
self.material not in self._app.materials.mat_names_aedt
and self.material not in self._app.materials.mat_names_aedt_lower
):
self._app.logger.warning("Material not found. Create the material before assigning it.")
return False
self.set_variables_in_hfss()
# Solution type: Modal
self._app.solution_type = "Modal"
# Map parameters
wg_length = self.synthesis_parameters.wg_length.hfss_variable
flare = self.synthesis_parameters.flare.hfss_variable
horn_length = self.synthesis_parameters.horn_length.hfss_variable
wg_width = self.synthesis_parameters.wg_width.hfss_variable
wg_height = self.synthesis_parameters.wg_height.hfss_variable
wall_thickness = self.synthesis_parameters.wall_thickness.hfss_variable
pos_x = self.synthesis_parameters.pos_x.hfss_variable
pos_y = self.synthesis_parameters.pos_y.hfss_variable
pos_z = self.synthesis_parameters.pos_z.hfss_variable
antenna_name = self.name
coordinate_system = self.coordinate_system
# Base of the horn
# Air
air = self._app.modeler.create_box(
origin=[
"-" + wg_width + "/2",
"-" + wg_height + "/2",
"-" + wg_length,
],
sizes=[wg_width, wg_height, wg_length],
material="vacuum",
)
air.history().props["Coordinate System"] = coordinate_system
# Wall
wall = self._app.modeler.create_box(
origin=[
"-" + wg_width + "/2" + "-" + wall_thickness,
"-" + wg_height + "/2" + "-" + wall_thickness,
"-" + wg_length,
],
sizes=[
wg_width + "+2*" + wall_thickness,
wg_height + "+2*" + wall_thickness,
wg_length,
],
name="wall_" + antenna_name,
material="vacuum",
)
wall.history().props["Coordinate System"] = coordinate_system
# Subtract
new_wall = self._app.modeler.subtract(tool_list=[air.name], blank_list=[wall.name], keep_originals=False)
# Top of the horn
# Input
wg_in = self._app.modeler.create_box(
origin=[
"-" + wg_width + "/2",
"-" + wg_height + "/2",
"-" + wg_length,
],
sizes=[wg_width, wg_height, wg_length],
name="wg_inner" + antenna_name,
material="vacuum",
)
wg_in.history().props["Coordinate System"] = coordinate_system
wg_in.color = (128, 255, 255)
# Cap
cap = self._app.modeler.create_box(
origin=[
"-" + wg_width + "/2" + "-" + wall_thickness,
"-" + wg_height + "/2" + "-" + wall_thickness,
"-" + wg_length,
],
sizes=[
wg_width + "+" + "2*" + wall_thickness,
wg_height + "+2*" + wall_thickness,
"-" + wall_thickness,
],
name="port_cap_" + antenna_name,
material="pec",
)
cap.history().props["Coordinate System"] = coordinate_system
cap.color = (132, 132, 193)
# P1
p1 = self._app.modeler.create_rectangle(
orientation=2,
origin=[
"-" + wg_width + "/2",
"-" + wg_height + "/2",
"-" + wg_length,
],
sizes=[wg_width, wg_height],
name="port_" + antenna_name,
)
p1.color = (128, 0, 0)
p1.history().props["Coordinate System"] = coordinate_system
# Horn wall
base = self._app.modeler.create_rectangle(
orientation=2,
origin=[
"-" + wg_width + "/2",
"-" + wg_height + "/2",
"0",
],
sizes=[wg_width, wg_height],
name="base_" + antenna_name,
)
base.history().props["Coordinate System"] = coordinate_system
base_wall = self._app.modeler.create_rectangle(
orientation=2,
origin=[
"-" + wg_width + "/2" + "-" + wall_thickness,
"-" + wg_height + "/2" + "-" + wall_thickness,
"0",
],
sizes=[
wg_width + "+" + "2*" + wall_thickness,
wg_height + "+2*" + wall_thickness,
],
name="base_wall_" + antenna_name,
)
base_wall.history().props["Coordinate System"] = coordinate_system
horn_top = self._app.modeler.create_rectangle(
orientation=2,
origin=[
"-" + flare + "/2",
"-" + wg_height + "/2",
horn_length,
],
sizes=[flare, wg_height],
name="horn_top_" + antenna_name,
)
horn_top.history().props["Coordinate System"] = coordinate_system
horn = self._app.modeler.create_rectangle(
orientation=2,
origin=[
"-" + flare + "/2" + "-" + wall_thickness,
"-" + wg_height + "/2" + "-" + wall_thickness,
horn_length,
],
sizes=[
flare + "+" + "2*" + wall_thickness,
wg_height + "+" + "2*" + wall_thickness,
],
name="horn_" + antenna_name,
)
horn.history().props["Coordinate System"] = coordinate_system
self._app.modeler.connect([horn, base_wall])
self._app.modeler.connect([base, horn_top])
new_wall = self._app.modeler.subtract(tool_list=[base.name], blank_list=[horn.name], keep_originals=False)
new_horn = self._app.modeler.unite([horn.name, wall.name])
horn.color = (132, 132, 193)
horn.material_name = self.material
# Air base
air_base = self._app.modeler.create_rectangle(
orientation=2,
origin=[
"-" + wg_width + "/2",
"-" + wg_height + "/2",
"0",
],
sizes=[
wg_width,
wg_height,
],
name="air_base_" + antenna_name,
)
air_base.history().props["Coordinate System"] = coordinate_system
# Air top
air_top = self._app.modeler.create_rectangle(
orientation=2,
origin=[
"-" + flare + "/2",
"-" + wg_height + "/2",
horn_length,
],
sizes=[
flare,
wg_height,
],
name="air_top_" + antenna_name,
)
air_top.history().props["Coordinate System"] = coordinate_system
self._app.modeler.connect([air_base.name, air_top.name])
self._app.modeler.unite([wg_in, air_base])
self.object_list[cap.name] = cap
self.object_list[horn.name] = horn
self.object_list[wg_in.name] = wg_in
self.object_list[p1.name] = p1
self._app.modeler.move([cap, horn, wg_in, p1], [pos_x, pos_y, pos_z])
cap.group_name = antenna_name
horn.group_name = antenna_name
wg_in.group_name = antenna_name
p1.group_name = antenna_name
[docs]
@pyaedt_function_handler()
def model_disco(self):
"""Model in PyDiscovery. To be implemented."""
pass
[docs]
@pyaedt_function_handler()
def setup_disco(self):
"""Set up model in PyDiscovery. To be implemented."""
pass
[docs]
class Pyramidal(CommonHorn):
"""Manages a pyramidal horn antenna.
This class is accessible through the app hfss object [1]_.
Parameters
----------
frequency : float, optional
Center frequency. The default is ``10.0``.
frequency_unit : str, optional
Frequency units. The default is ``"GHz"``.
material : str, optional
Horn material. If a material is not defined, a new material, ``parametrized``, is defined.
The default is ``"pec"``.
outer_boundary : str, optional
Boundary type to use. The default is ``None``. Options are ``"FEBI"``, ``"PML"``,
``"Radiation"``, and ``None``.
length_unit : str, optional
Length units. The default is ``"mm"``.
parametrized : bool, optional
Whether to create a parametrized antenna. The default is ``True``.
Returns
-------
:class:`aedt.toolkits.antenna.Pyramidal`
Pyramidal horn object.
Notes
-----
.. [1] C. Balanis, "Aperture Antennas: Analysis, Design, and Applications,"
*Modern Antenna Handbook*, New York, 2008.
Examples
--------
>>> from ansys.aedt.toolkits.antenna.backend.antenna_models.horn import Pyramidal
>>> import ansys.aedt.core
>>> app = ansys.aedt.core.Hfss()
>>> oantenna1 = Pyramidal(app)
>>> oantenna1.frequency = 12.0
>>> oantenna1.model_hfss()
>>> oantenna1.setup_hfss()
>>> oantenna2 = Pyramidal(app, origin=[0.2, 0.5, 0])
>>> oantenna2.model_hfss()
>>> oantenna2.setup_hfss()
>>> app.release_desktop(False, False)
"""
_default_input_parameters = {
"name": None,
"origin": [0, 0, 0],
"length_unit": None,
"coordinate_system": "Global",
"frequency": 10.0,
"frequency_unit": "GHz",
"material": "pec",
"outer_boundary": None,
}
def __init__(self, *args, **kwargs):
CommonHorn.__init__(self, self._default_input_parameters, *args, **kwargs)
self._parameters = self.synthesis()
self.update_synthesis_parameters(self._parameters)
self.antenna_type = "Pyramidal"
[docs]
@pyaedt_function_handler()
def synthesis(self):
"""Antenna synthesis.
Returns
-------
dict
Analytical parameters.
"""
parameters = {}
freq_ghz = constants.unit_converter(self.frequency, "Freq", self.frequency_unit, "GHz")
scale = lambda x: (10.0 / freq_ghz) * x
def scale_value(value, round_val=3, doScale=True):
if doScale:
value = scale(value)
return round(value, round_val)
wg_length_in = scale_value(1.0)
flare_a_in = scale_value(1.8)
flare_b_in = scale_value(1.4)
horn_length_in = scale_value(3.0)
wg_obj = StandardWaveguide()
wg_name = wg_obj.find_waveguide(freq_ghz)
if wg_name:
wg_dim_in = wg_obj.get_waveguide_dimensions(wg_name, self.length_unit)
wg_a = wg_dim_in[0]
wg_b = wg_dim_in[1]
wall_thickness = wg_dim_in[2]
else:
wg_a_in = scale_value(0.9)
wg_a = constants.unit_converter(wg_a_in, "Length", "in", self.length_unit)
wg_b_in = scale_value(0.4)
wg_b = constants.unit_converter(wg_b_in, "Length", "in", self.length_unit)
wall_thickness_in = scale_value(0.02)
wall_thickness = constants.unit_converter(wall_thickness_in, "Length", "in", self.length_unit)
wg_length = constants.unit_converter(wg_length_in, "Length", "in", self.length_unit)
parameters["wg_length"] = wg_length
flare_a = constants.unit_converter(flare_a_in, "Length", "in", self.length_unit)
parameters["flare_a"] = flare_a
flare_b = constants.unit_converter(flare_b_in, "Length", "in", self.length_unit)
parameters["flare_b"] = flare_b
horn_length = constants.unit_converter(horn_length_in, "Length", "in", self.length_unit)
parameters["horn_length"] = horn_length
parameters["wg_width"] = wg_a
parameters["wg_height"] = wg_b
parameters["wall_thickness"] = wall_thickness
parameters["pos_x"] = self.origin[0]
parameters["pos_y"] = self.origin[1]
parameters["pos_z"] = self.origin[2]
myKeys = list(parameters.keys())
myKeys.sort()
parameters_out = OrderedDict([(i, parameters[i]) for i in myKeys])
return parameters_out
[docs]
@pyaedt_function_handler()
def model_hfss(self):
"""Draw pyramidal horn antenna.
Once the antenna is created, this method is not used anymore."""
if self.object_list:
self._app.logger.warning("This antenna already exists.")
return False
if (
self.material not in self._app.materials.mat_names_aedt
and self.material not in self._app.materials.mat_names_aedt_lower
):
self._app.logger.warning("Material not found. Create the material before assigning it.")
return False
self.set_variables_in_hfss()
# Solution type: Modal
self._app.solution_type = "Modal"
# Map parameters
wg_length = self.synthesis_parameters.wg_length.hfss_variable
flare_a = self.synthesis_parameters.flare_a.hfss_variable
flare_b = self.synthesis_parameters.flare_b.hfss_variable
horn_length = self.synthesis_parameters.horn_length.hfss_variable
wg_width = self.synthesis_parameters.wg_width.hfss_variable
wg_height = self.synthesis_parameters.wg_height.hfss_variable
wall_thickness = self.synthesis_parameters.wall_thickness.hfss_variable
pos_x = self.synthesis_parameters.pos_x.hfss_variable
pos_y = self.synthesis_parameters.pos_y.hfss_variable
pos_z = self.synthesis_parameters.pos_z.hfss_variable
antenna_name = self.name
coordinate_system = self.coordinate_system
# Base of the horn
# Air
air = self._app.modeler.create_box(
origin=[
"-" + wg_width + "/2",
"-" + wg_height + "/2",
"-" + wg_length,
],
sizes=[wg_width, wg_height, wg_length],
material="vacuum",
)
air.history().props["Coordinate System"] = coordinate_system
# Wall
wall = self._app.modeler.create_box(
origin=[
"-" + wg_width + "/2" + "-" + wall_thickness,
"-" + wg_height + "/2" + "-" + wall_thickness,
"-" + wg_length,
],
sizes=[
wg_width + "+2*" + wall_thickness,
wg_height + "+2*" + wall_thickness,
wg_length,
],
name="wall_" + antenna_name,
material="vacuum",
)
wall.history().props["Coordinate System"] = coordinate_system
# Subtract
new_wall = self._app.modeler.subtract(tool_list=[air.name], blank_list=[wall.name], keep_originals=False)
# Top of the horn
# Input
wg_in = self._app.modeler.create_box(
origin=[
"-" + wg_width + "/2",
"-" + wg_height + "/2",
"-" + wg_length,
],
sizes=[wg_width, wg_height, wg_length],
name="wg_inner" + antenna_name,
material="vacuum",
)
wg_in.history().props["Coordinate System"] = coordinate_system
wg_in.color = (128, 255, 255)
# Cap
cap = self._app.modeler.create_box(
origin=[
"-" + wg_width + "/2" + "-" + wall_thickness,
"-" + wg_height + "/2" + "-" + wall_thickness,
"-" + wg_length,
],
sizes=[
wg_width + "+" + "2*" + wall_thickness,
wg_height + "+2*" + wall_thickness,
"-" + wall_thickness,
],
name="port_cap_" + antenna_name,
material="pec",
)
cap.history().props["Coordinate System"] = coordinate_system
cap.color = (132, 132, 193)
# P1
p1 = self._app.modeler.create_rectangle(
orientation=2,
origin=[
"-" + wg_width + "/2",
"-" + wg_height + "/2",
"-" + wg_length,
],
sizes=[wg_width, wg_height],
name="port_" + antenna_name,
)
p1.color = (128, 0, 0)
p1.history().props["Coordinate System"] = coordinate_system
# Horn wall
base = self._app.modeler.create_rectangle(
orientation=2,
origin=[
"-" + wg_width + "/2",
"-" + wg_height + "/2",
"0",
],
sizes=[wg_width, wg_height],
name="base_" + antenna_name,
)
base.history().props["Coordinate System"] = coordinate_system
base_wall = self._app.modeler.create_rectangle(
orientation=2,
origin=[
"-" + wg_width + "/2" + "-" + wall_thickness,
"-" + wg_height + "/2" + "-" + wall_thickness,
"0",
],
sizes=[
wg_width + "+" + "2*" + wall_thickness,
wg_height + "+2*" + wall_thickness,
],
name="base_wall_" + antenna_name,
)
base_wall.history().props["Coordinate System"] = coordinate_system
horn_top = self._app.modeler.create_rectangle(
orientation=2,
origin=[
"-" + flare_a + "/2",
"-" + flare_b + "/2",
horn_length,
],
sizes=[flare_a, flare_b],
name="horn_top_" + antenna_name,
)
horn_top.history().props["Coordinate System"] = coordinate_system
horn = self._app.modeler.create_rectangle(
orientation=2,
origin=[
"-" + flare_a + "/2" + "-" + wall_thickness,
"-" + flare_b + "/2" + "-" + wall_thickness,
horn_length,
],
sizes=[
flare_a + "+" + "2*" + wall_thickness,
flare_b + "+" + "2*" + wall_thickness,
],
name="horn_" + antenna_name,
)
horn.history().props["Coordinate System"] = coordinate_system
self._app.modeler.connect([horn, base_wall])
self._app.modeler.connect([base, horn_top])
new_wall = self._app.modeler.subtract(tool_list=[base.name], blank_list=[horn.name], keep_originals=False)
new_horn = self._app.modeler.unite([horn.name, wall.name])
horn.color = (132, 132, 193)
horn.material_name = self.material
# Air base
air_base = self._app.modeler.create_rectangle(
orientation=2,
origin=[
"-" + wg_width + "/2",
"-" + wg_height + "/2",
"0",
],
sizes=[
wg_width,
wg_height,
],
name="air_base_" + antenna_name,
)
air_base.history().props["Coordinate System"] = coordinate_system
# Air top
air_top = self._app.modeler.create_rectangle(
orientation=2,
origin=[
"-" + flare_a + "/2",
"-" + flare_b + "/2",
horn_length,
],
sizes=[
flare_a,
flare_b,
],
name="air_top_" + antenna_name,
)
air_top.history().props["Coordinate System"] = coordinate_system
self._app.modeler.connect([air_base.name, air_top.name])
self._app.modeler.unite([wg_in, air_base])
self.object_list[cap.name] = cap
self.object_list[horn.name] = horn
self.object_list[wg_in.name] = wg_in
self.object_list[p1.name] = p1
self._app.modeler.move([cap, horn, wg_in, p1], [pos_x, pos_y, pos_z])
cap.group_name = antenna_name
horn.group_name = antenna_name
wg_in.group_name = antenna_name
p1.group_name = antenna_name
[docs]
@pyaedt_function_handler()
def model_disco(self):
"""Model in PyDiscovery. To be implemented."""
pass
[docs]
@pyaedt_function_handler()
def setup_disco(self):
"""Set up model in PyDiscovery. To be implemented."""
pass
[docs]
class QuadRidged(CommonHorn):
"""Manages a quad-ridged horn antenna.
This class is accessible through the app hfss object [1]_, [2]_, [3]_.
Parameters
----------
frequency : float, optional
Center frequency. The default is ``10.0``.
frequency_unit : str, optional
Frequency units. The default is ``"GHz"``.
material : str, optional
Horn material. If a material is not defined, a new material, ``parametrized``, is defined.
The default is ``"pec"``.
outer_boundary : str, optional
Boundary type to use. The default is ``None``. Options are ``"FEBI"``, ``"PML"``,
``"Radiation"``, and ``None``.
length_unit : str, optional
Length units. The default is ``"mm"``.
parametrized : bool, optional
Whether to create a parametrized antenna. The default is ``True``.
Returns
-------
:class:`aedt.toolkits.antenna.PyramidalRidged`
Pyramidal ridged horn object.
Notes
-----
.. [1] K. L. Walton and V. C. Sundberg, "Broadband ridged horn design,"
Microwave J., vol. 4, pp. 96-101, Apr. 1964.
.. [2] C. Bruns et al., "Analysis and Simulations of a 1-18 GHz
Broadband Double-Ridged Horn Antenna,"
IEEE Electromag. Compat., vol. 45, pp. 55-60, Feb 2003.
.. [3] C. Balanis, "Horn Antennas," Antenna Theory Analysis,
3rd ed. Hoboken: Wiley, 2005, ch. 13.
Examples
--------
>>> from ansys.aedt.toolkits.antenna.backend.antenna_models.horn import QuadRidged
>>> import ansys.aedt.core
>>> app = ansys.aedt.core.Hfss()
>>> oantenna1 = QuadRidged(app)
>>> oantenna1.frequency = 12.0
>>> oantenna1.model_hfss()
>>> oantenna1.setup_hfss()
>>> oantenna2 = QuadRidged(app, origin=[0.2, 0.5, 0])
>>> oantenna2.model_hfss()
>>> oantenna2.setup_hfss()
>>> app.release_desktop(False, False)
"""
_default_input_parameters = {
"name": None,
"origin": [0, 0, 0],
"length_unit": None,
"coordinate_system": "Global",
"frequency": 10.0,
"frequency_unit": "GHz",
"material": "pec",
"outer_boundary": None,
}
def __init__(self, *args, **kwargs):
CommonHorn.__init__(self, self._default_input_parameters, *args, **kwargs)
self._parameters = self.synthesis()
self.update_synthesis_parameters(self._parameters)
self.antenna_type = "QuadRidged"
[docs]
@pyaedt_function_handler()
def synthesis(self):
"""Antenna synthesis.
Returns
-------
dict
Analytical parameters.
"""
parameters = {}
freq_ghz = constants.unit_converter(self.frequency, "Freq", self.frequency_unit, "GHz")
scale = lambda x: (5.0 / freq_ghz) * x
def scale_value(value, round_val=3, doScale=True):
if doScale:
value = scale(value)
return round(value, round_val)
aperture_width = scale_value(89.6)
flare_length = scale_value(64.0)
wall_thickness = scale_value(5.0)
wg_width = scale_value(25.6)
wg_length = scale_value(64.0)
ridge_width = scale_value(4.48)
ridge_spacing = scale_value(4.8)
ridge_height_1 = scale_value(10.4)
ridge_height_2 = scale_value(12.96)
ridge_height_3 = scale_value(14.56)
ridge_height_4 = scale_value(16.0)
ridge_height_5 = scale_value(16.96)
ridge_height_6 = scale_value(16.48)
ridge_height_7 = scale_value(16.0)
ridge_height_8 = scale_value(14.56)
ridge_height_9 = scale_value(12.64)
ridge_height_10 = scale_value(9.92)
parameters["aperture_width"] = aperture_width
flare_length = constants.unit_converter(flare_length, "Length", "mm", self.length_unit)
parameters["flare_length"] = flare_length
wall_thickness = constants.unit_converter(wall_thickness, "Length", "mm", self.length_unit)
parameters["wall_thickness"] = wall_thickness
wg_width = constants.unit_converter(wg_width, "Length", "mm", self.length_unit)
parameters["wg_width"] = wg_width
wg_length = constants.unit_converter(wg_length, "Length", "mm", self.length_unit)
parameters["wg_length"] = wg_length
ridge_width = constants.unit_converter(ridge_width, "Length", "mm", self.length_unit)
parameters["ridge_width"] = ridge_width
ridge_spacing = constants.unit_converter(ridge_spacing, "Length", "mm", self.length_unit)
parameters["ridge_spacing"] = ridge_spacing
ridge_height_1 = constants.unit_converter(ridge_height_1, "Length", "mm", self.length_unit)
parameters["ridge_height_1"] = ridge_height_1
ridge_height_2 = constants.unit_converter(ridge_height_2, "Length", "mm", self.length_unit)
parameters["ridge_height_2"] = ridge_height_2
ridge_height_3 = constants.unit_converter(ridge_height_3, "Length", "mm", self.length_unit)
parameters["ridge_height_3"] = ridge_height_3
ridge_height_4 = constants.unit_converter(ridge_height_4, "Length", "mm", self.length_unit)
parameters["ridge_height_4"] = ridge_height_4
ridge_height_5 = constants.unit_converter(ridge_height_5, "Length", "mm", self.length_unit)
parameters["ridge_height_5"] = ridge_height_5
ridge_height_6 = constants.unit_converter(ridge_height_6, "Length", "mm", self.length_unit)
parameters["ridge_height_6"] = ridge_height_6
ridge_height_7 = constants.unit_converter(ridge_height_7, "Length", "mm", self.length_unit)
parameters["ridge_height_7"] = ridge_height_7
ridge_height_8 = constants.unit_converter(ridge_height_8, "Length", "mm", self.length_unit)
parameters["ridge_height_8"] = ridge_height_8
ridge_height_9 = constants.unit_converter(ridge_height_9, "Length", "mm", self.length_unit)
parameters["ridge_height_9"] = ridge_height_9
ridge_height_10 = constants.unit_converter(ridge_height_10, "Length", "mm", self.length_unit)
parameters["ridge_height_10"] = ridge_height_10
parameters["pos_x"] = self.origin[0]
parameters["pos_y"] = self.origin[1]
parameters["pos_z"] = self.origin[2]
myKeys = list(parameters.keys())
myKeys.sort()
parameters_out = OrderedDict([(i, parameters[i]) for i in myKeys])
return parameters_out
[docs]
@pyaedt_function_handler()
def model_hfss(self):
"""Draw conical horn antenna.
Once the antenna is created, this method is not used anymore."""
if self.object_list:
self._app.logger.warning("This antenna already exists.")
return False
if (
self.material not in self._app.materials.mat_names_aedt
and self.material not in self._app.materials.mat_names_aedt_lower
):
self._app.logger.warning("Material not found. Create the material before assigning it.")
return False
self.set_variables_in_hfss()
# Solution type: Modal
self._app.solution_type = "Modal"
# Map parameters
aperture_width = self.synthesis_parameters.aperture_width.hfss_variable
flare_length = self.synthesis_parameters.flare_length.hfss_variable
wall_thickness = self.synthesis_parameters.wall_thickness.hfss_variable
wg_width = self.synthesis_parameters.wg_width.hfss_variable
wg_length = self.synthesis_parameters.wg_length.hfss_variable
ridge_width = self.synthesis_parameters.ridge_width.hfss_variable
ridge_spacing = self.synthesis_parameters.ridge_spacing.hfss_variable
ridge_height_1 = self.synthesis_parameters.ridge_height_1.hfss_variable
ridge_height_2 = self.synthesis_parameters.ridge_height_2.hfss_variable
ridge_height_3 = self.synthesis_parameters.ridge_height_3.hfss_variable
ridge_height_4 = self.synthesis_parameters.ridge_height_4.hfss_variable
ridge_height_5 = self.synthesis_parameters.ridge_height_5.hfss_variable
ridge_height_6 = self.synthesis_parameters.ridge_height_6.hfss_variable
ridge_height_7 = self.synthesis_parameters.ridge_height_7.hfss_variable
ridge_height_8 = self.synthesis_parameters.ridge_height_8.hfss_variable
ridge_height_9 = self.synthesis_parameters.ridge_height_9.hfss_variable
ridge_height_10 = self.synthesis_parameters.ridge_height_10.hfss_variable
pos_x = self.synthesis_parameters.pos_x.hfss_variable
pos_y = self.synthesis_parameters.pos_y.hfss_variable
pos_z = self.synthesis_parameters.pos_z.hfss_variable
antenna_name = self.name
coordinate_system = self.coordinate_system
# Base of the horn
# Air
air = self._app.modeler.create_box(
origin=[
"-" + wg_width + "/2",
"-" + wg_width + "/2",
"-" + wg_length,
],
sizes=[wg_width, wg_width, wg_length],
material="vacuum",
)
air.history().props["Coordinate System"] = coordinate_system
# Wall
wall = self._app.modeler.create_box(
origin=[
"-" + wg_width + "/2" + "-" + wall_thickness,
"-" + wg_width + "/2" + "-" + wall_thickness,
"-" + wg_length,
],
sizes=[
wg_width + "+2*" + wall_thickness,
wg_width + "+2*" + wall_thickness,
wg_length,
],
name="wall_" + antenna_name,
material="vacuum",
)
wall.history().props["Coordinate System"] = coordinate_system
# Subtract
new_wall = self._app.modeler.subtract(tool_list=[air.name], blank_list=[wall.name], keep_originals=False)
# Top of the horn
# Input
wg_in = self._app.modeler.create_box(
origin=[
"-" + wg_width + "/2",
"-" + wg_width + "/2",
"-" + wg_length,
],
sizes=[wg_width, wg_width, wg_length],
name="wg_inner" + antenna_name,
material="vacuum",
)
wg_in.history().props["Coordinate System"] = coordinate_system
wg_in.color = (128, 255, 255)
# Cap
cap = self._app.modeler.create_box(
origin=[
"-" + wg_width + "/2" + "-" + wall_thickness,
"-" + wg_width + "/2" + "-" + wall_thickness,
"-" + wg_length,
],
sizes=[
wg_width + "+" + "2*" + wall_thickness,
wg_width + "+2*" + wall_thickness,
"-" + wall_thickness,
],
name="port_cap_" + antenna_name,
material="pec",
)
cap.history().props["Coordinate System"] = coordinate_system
cap.color = (132, 132, 193)
# P1
p1 = self._app.modeler.create_rectangle(
orientation=2,
origin=[
"-" + wg_width + "/2",
"-" + wg_width + "/2",
"-" + wg_length,
],
sizes=[wg_width, wg_width],
name="port_" + antenna_name,
)
p1.color = (128, 0, 0)
p1.history().props["Coordinate System"] = coordinate_system
# Horn wall
base = self._app.modeler.create_rectangle(
orientation=2,
origin=[
"-" + wg_width + "/2",
"-" + wg_width + "/2",
"0",
],
sizes=[wg_width, wg_width],
name="base_" + antenna_name,
)
base.history().props["Coordinate System"] = coordinate_system
base_wall = self._app.modeler.create_rectangle(
orientation=2,
origin=[
"-" + wg_width + "/2" + "-" + wall_thickness,
"-" + wg_width + "/2" + "-" + wall_thickness,
"0",
],
sizes=[
wg_width + "+" + "2*" + wall_thickness,
wg_width + "+2*" + wall_thickness,
],
name="base_wall_" + antenna_name,
)
base_wall.history().props["Coordinate System"] = coordinate_system
horn_top = self._app.modeler.create_rectangle(
orientation=2,
origin=[
"-" + aperture_width + "/2",
"-" + aperture_width + "/2",
flare_length,
],
sizes=[aperture_width, aperture_width],
name="horn_top_" + antenna_name,
)
horn_top.history().props["Coordinate System"] = coordinate_system
horn = self._app.modeler.create_rectangle(
orientation=2,
origin=[
"-" + aperture_width + "/2" + "-" + wall_thickness,
"-" + aperture_width + "/2" + "-" + wall_thickness,
flare_length,
],
sizes=[
aperture_width + "+" + "2*" + wall_thickness,
aperture_width + "+" + "2*" + wall_thickness,
],
name="horn_" + antenna_name,
)
horn.history().props["Coordinate System"] = coordinate_system
# Ridge
position_ridge_1 = []
position_ridge_2 = []
position_ridge_3 = []
position_ridge_4 = []
ridged_tapers = [
ridge_height_1,
ridge_height_2,
ridge_height_3,
ridge_height_4,
ridge_height_5,
ridge_height_6,
ridge_height_7,
ridge_height_8,
ridge_height_9,
ridge_height_10,
]
x = "0"
for i in range(10):
y = (
"("
+ wg_width
+ "/2+("
+ aperture_width
+ "-"
+ wg_width
+ ")/2*"
+ str(i)
+ "/10-"
+ str(ridged_tapers[i])
+ ")"
)
z = flare_length + "*" + str(i) + "/10"
position_ridge_1.append([x, y, z])
position_ridge_2.append([x, "-" + y, z])
position_ridge_3.append([y, x, z])
position_ridge_4.append(["-" + y, x, z])
y = aperture_width + "/2"
z = flare_length
position_ridge_1.append([x, y, z])
position_ridge_2.append([x, "-" + y, z])
position_ridge_3.append([y, x, z])
position_ridge_4.append(["-" + y, x, z])
y = wg_width + "/2"
z = "0"
position_ridge_1.append([x, y, z])
position_ridge_2.append([x, "-" + y, z])
position_ridge_3.append([y, x, z])
position_ridge_4.append(["-" + y, x, z])
ridge1 = self._app.modeler.create_polyline(
position_list=position_ridge_1,
cover_surface=True,
name="ridge_1" + antenna_name,
material=self.material,
)
ridge1 = self._app.modeler.thicken_sheet(ridge1, ridge_width, True)
ridge1.history().props["Coordinate System"] = coordinate_system
ridge1.color = (132, 132, 193)
ridge2 = self._app.modeler.create_polyline(
position_list=position_ridge_2,
cover_surface=True,
name="ridge_2" + antenna_name,
material=self.material,
)
ridge2 = self._app.modeler.thicken_sheet(ridge2, ridge_width, True)
ridge2.history().props["Coordinate System"] = coordinate_system
ridge2.color = (132, 132, 193)
ridge3 = self._app.modeler.create_polyline(
position_list=position_ridge_3,
cover_surface=True,
name="ridge_3" + antenna_name,
material=self.material,
)
ridge3 = self._app.modeler.thicken_sheet(ridge3, ridge_width, True)
ridge3.history().props["Coordinate System"] = coordinate_system
ridge3.color = (132, 132, 193)
ridge4 = self._app.modeler.create_polyline(
position_list=position_ridge_4,
cover_surface=True,
name="ridge_4" + antenna_name,
material=self.material,
)
ridge4 = self._app.modeler.thicken_sheet(ridge4, ridge_width, True)
ridge4.history().props["Coordinate System"] = coordinate_system
ridge4.color = (132, 132, 193)
# Connectors of the ridge
# Connector
connector1 = self._app.modeler.create_box(
origin=[
"-" + ridge_width + "/2",
"-" + wg_width + "/2",
"-" + wg_length,
],
sizes=[
ridge_width,
"(" + wg_width + "-" + ridge_spacing + ")/2",
wg_length,
],
name="connector_" + antenna_name,
material="pec",
)
connector1.history().props["Coordinate System"] = coordinate_system
connector1.color = (132, 132, 193)
connector2 = self._app.modeler.create_box(
origin=[
"-" + ridge_width + "/2",
wg_width + "/2",
"-" + wg_length,
],
sizes=[
ridge_width,
"-(" + wg_width + "-" + ridge_spacing + ")/2",
wg_length,
],
name="connector_" + antenna_name,
material="pec",
)
connector2.history().props["Coordinate System"] = coordinate_system
connector2.color = (132, 132, 193)
connector3 = self._app.modeler.create_box(
origin=[
"-" + wg_width + "/2",
"-" + ridge_width + "/2",
"-" + wg_length,
],
sizes=[
"(" + wg_width + "-" + ridge_spacing + ")/2",
ridge_width,
wg_length,
],
name="connector_" + antenna_name,
material="pec",
)
connector3.history().props["Coordinate System"] = coordinate_system
connector3.color = (132, 132, 193)
connector4 = self._app.modeler.create_box(
origin=[
wg_width + "/2",
"-" + ridge_width + "/2",
"-" + wg_length,
],
sizes=[
"-(" + wg_width + "-" + ridge_spacing + ")/2",
ridge_width,
wg_length,
],
name="connector_" + antenna_name,
material="pec",
)
connector4.history().props["Coordinate System"] = coordinate_system
connector4.color = (132, 132, 193)
# Connect pieces
self._app.modeler.connect([horn.name, base_wall.name])
self._app.modeler.connect([base.name, horn_top.name])
self._app.modeler.subtract(horn.name, base.name, False)
self._app.modeler.unite(
[
horn,
wall,
ridge1,
ridge2,
ridge3,
ridge4,
connector1,
connector2,
connector3,
connector4,
]
)
horn.color = (255, 128, 65)
horn.material_name = self.material
# Air base
air_base = self._app.modeler.create_rectangle(
orientation=2,
origin=[
"-" + wg_width + "/2",
"-" + wg_width + "/2",
"0",
],
sizes=[
wg_width,
wg_width,
],
name="air_base_" + antenna_name,
)
air_base.history().props["Coordinate System"] = coordinate_system
# Air top
air_top = self._app.modeler.create_rectangle(
orientation=2,
origin=[
"-" + aperture_width + "/2",
"-" + aperture_width + "/2",
flare_length,
],
sizes=[
aperture_width,
aperture_width,
],
name="air_top_" + antenna_name,
)
air_top.history().props["Coordinate System"] = coordinate_system
self._app.modeler.connect([air_base.name, air_top.name])
self._app.modeler.unite([wg_in, air_base])
self.object_list[cap.name] = cap
self.object_list[horn.name] = horn
self.object_list[wg_in.name] = wg_in
self.object_list[p1.name] = p1
self._app.modeler.move([cap, horn, wg_in, p1], [pos_x, pos_y, pos_z])
self._app.change_material_override(True)
cap.group_name = antenna_name
horn.group_name = antenna_name
wg_in.group_name = antenna_name
p1.group_name = antenna_name
[docs]
@pyaedt_function_handler()
def model_disco(self):
"""Model in PyDiscovery. To be implemented."""
pass
[docs]
@pyaedt_function_handler()
def setup_disco(self):
"""Set up model in PyDiscovery. To be implemented."""
pass
class Conical_Special(CommonHorn):
"""Manages a conical horn antenna.
This class is accessible through the app hfss object [1]_.
Parameters
----------
frequency : float, optional
Center frequency. The default is ``10.0``.
frequency_unit : str, optional
Frequency units. The default is ``"GHz"``.
material : str, optional
Horn material. If a material is not defined, a new material, ``parametrized``, is defined.
The default is ``"pec"``.
outer_boundary : str, optional
Boundary type to use. The default is ``None``. Options are ``"FEBI"``, ``"PML"``,
``"Radiation"``, and ``None``.
length_unit : str, optional
Length units. The default is ``"mm"``.
parametrized : bool, optional
Whether to create a parametrized antenna. The default is ``True``.
Returns
-------
:class:`aedt.toolkits.antenna.ConicalHorn`
Conical horn object.
Notes
-----
.. [1] C. Balanis, "Aperture Antennas: Analysis, Design, and Applications,"
*Modern Antenna Handbook*, New York, 2008.
Examples
--------
>>> from ansys.aedt.toolkits.antenna.backend.antenna_models.horn import Conical
>>> import ansys.aedt.core
>>> oantenna1 = Conical()
>>> oantenna1.frequency = 12.0
>>> app = ansys.aedt.core.Hfss()
>>> oantenna1 = Conical(app)
>>> oantenna1.model_hfss()
>>> oantenna1.setup_hfss()
>>> oantenna2 = Conical(app, origin=[0.2, 0.5, 0])
>>> oantenna2.model_hfss()
>>> oantenna2.setup_hfss()
>>> app.release_desktop(False, False)
"""
_default_input_parameters = {
"name": "",
"origin": [0, 0, 0],
"length_unit": None,
"coordinate_system": "Global",
"frequency": 10.0,
"frequency_unit": "GHz",
"material": "pec",
"outer_boundary": "",
}
def __init__(self, *args, **kwargs):
CommonHorn.__init__(self, self._default_input_parameters, *args, **kwargs)
self._parameters = self.synthesis()
self.update_synthesis_parameters(self._parameters)
self.antenna_type = "Conical"
@pyaedt_function_handler()
def synthesis(self):
"""Antenna synthesis.
Returns
-------
dict
Analytical parameters.
"""
parameters = {}
lightSpeed = constants.SpeedOfLight # m/s
freq_hz = constants.unit_converter(self.frequency, "Freq", self.frequency_unit, "Hz")
wavelength = lightSpeed / freq_hz
wavelength_in = constants.unit_converter(wavelength, "Length", "meter", "in")
wg_radius_in = 0.5 * wavelength_in
wg_length_in = 0.4 * wavelength_in
horn_radius_in = 1.4 * wavelength_in
horn_length_in = 2 * wavelength_in
wall_thickness_in = 0.02 * wavelength_in
wg_radius = constants.unit_converter(wg_radius_in, "Length", "in", self.length_unit)
parameters["wg_radius"] = wg_radius
wg_length = constants.unit_converter(wg_length_in, "Length", "in", self.length_unit)
parameters["wg_length"] = wg_length
horn_radius = constants.unit_converter(horn_radius_in, "Length", "in", self.length_unit)
parameters["horn_radius"] = horn_radius
horn_length = constants.unit_converter(horn_length_in, "Length", "in", self.length_unit)
parameters["horn_length"] = horn_length
wall_thickness = constants.unit_converter(wall_thickness_in, "Length", "in", self.length_unit)
parameters["wall_thickness"] = wall_thickness
parameters["pos_x"] = self.origin[0]
parameters["pos_y"] = self.origin[1]
parameters["pos_z"] = self.origin[2]
myKeys = list(parameters.keys())
myKeys.sort()
parameters_out = OrderedDict([(i, parameters[i]) for i in myKeys])
return parameters_out
@pyaedt_function_handler()
def model_hfss(self):
"""Draw a conical horn antenna.
Once the antenna is created, this method is not used anymore."""
if self.object_list:
logger.debug("This antenna already exists")
return False
if (
self.material not in self._app.materials.mat_names_aedt
and self.material not in self._app.materials.mat_names_aedt_lower
):
self._app.logger.warning("Material not found. Create the material before assigning it.")
return False
self.set_variables_in_hfss()
# Solution type: Modal
self._app.solution_type = "Modal"
# Map parameters
horn_length = self.synthesis_parameters.horn_length.hfss_variable
horn_radius = self.synthesis_parameters.horn_radius.hfss_variable
wall_thickness = self.synthesis_parameters.wall_thickness.hfss_variable
wg_length = self.synthesis_parameters.wg_length.hfss_variable
wg_radius = self.synthesis_parameters.wg_radius.hfss_variable
pos_x = self.synthesis_parameters.pos_x.hfss_variable
pos_y = self.synthesis_parameters.pos_y.hfss_variable
pos_z = self.synthesis_parameters.pos_z.hfss_variable
antenna_name = self.name
coordinate_system = self.coordinate_system
# Negative air
neg_air = self._app.modeler.create_cylinder(
orientation=2,
origin=["0", "0", "0"],
radius=wg_radius,
height="-" + wg_length,
material="vacuum",
)
neg_air.history().props["Coordinate System"] = coordinate_system
# Wall
wall = self._app.modeler.create_cylinder(
orientation=2,
origin=["0", "0", "0"],
radius=wg_radius + "+" + wall_thickness,
height="-" + wg_length,
name="wg_outer_" + antenna_name,
material=self.material,
)
wall.history().props["Coordinate System"] = coordinate_system
# Subtract
new_wall = self._app.modeler.subtract(tool_list=[neg_air.name], blank_list=[wall.name], keep_originals=False)
# Input
wg_in = self._app.modeler.create_cylinder(
orientation=2,
origin=["0", "0", "0"],
radius=wg_radius,
height="-" + wg_length,
name="wg_inner_" + antenna_name,
material="vacuum",
)
wg_in.history().props["Coordinate System"] = coordinate_system
# Cap
cap = self._app.modeler.create_cylinder(
orientation=2,
origin=["0", "0", "-" + wg_length],
radius=wg_radius + "+" + wall_thickness,
height="-" + wall_thickness,
name="port_cap_" + antenna_name,
material="pec",
)
cap.history().props["Coordinate System"] = coordinate_system
# P1
p1 = self._app.modeler.create_circle(
cs_plane=2,
origin=["0", "0", "-" + wg_length],
radius=wg_radius,
name="port_" + antenna_name,
)
p1.color = (128, 0, 0)
p1.history().props["Coordinate System"] = coordinate_system
# Horn wall
base = self._app.modeler.create_circle(
cs_plane=2,
origin=["0", "0", "0"],
radius=wg_radius,
)
base.history().props["Coordinate System"] = coordinate_system
base_wall = self._app.modeler.create_circle(
cs_plane=2,
origin=["0", "0", "0"],
radius=wg_radius + "+" + wall_thickness,
)
base_wall.history().props["Coordinate System"] = coordinate_system
horn_top = self._app.modeler.create_circle(
cs_plane=2,
origin=["0", "0", horn_length],
radius=horn_radius,
)
horn_top.history().props["Coordinate System"] = coordinate_system
horn_sheet = self._app.modeler.create_circle(
cs_plane=2,
origin=["0", "0", horn_length],
radius=horn_radius + "+" + wall_thickness,
)
horn_sheet.history().props["Coordinate System"] = coordinate_system
self._app.modeler.connect([horn_sheet.name, base_wall.name])
self._app.modeler.connect([base.name, horn_top.name])
# Horn
self._app.modeler.subtract(blank_list=[horn_sheet.name], tool_list=[base.name], keep_originals=False)
self._app.modeler.unite([horn_sheet.name, wall.name])
air_base = self._app.modeler.create_circle(
cs_plane=2,
origin=["0", "0", "0"],
radius=wg_radius,
)
air_base.history().props["Coordinate System"] = coordinate_system
air_top = self._app.modeler.create_circle(
cs_plane=2,
origin=["0", "0", horn_length],
radius=horn_radius,
)
air_top.history().props["Coordinate System"] = coordinate_system
self._app.modeler.connect([air_base, air_top])
self._app.modeler.unite([wg_in, air_base])
wg_in.name = "internal_" + antenna_name
wg_in.color = (128, 255, 255)
horn_sheet.name = "metal_" + antenna_name
horn_sheet.material_name = self.material
horn_sheet.color = (255, 128, 65)
cap.color = (132, 132, 192)
p1.color = (128, 0, 0)
self.object_list[wg_in.name] = wg_in
self.object_list[horn_sheet.name] = horn_sheet
self.object_list[cap.name] = cap
self.object_list[p1.name] = p1
self._app.modeler.move(list(self.object_list.keys()), [pos_x, pos_y, pos_z])
wg_in.group_name = antenna_name
horn_sheet.group_name = antenna_name
cap.group_name = antenna_name
p1.group_name = antenna_name
@pyaedt_function_handler()
def model_disco(self):
"""Model in PyDiscovery. To be implemented."""
pass
@pyaedt_function_handler()
def setup_disco(self):
"""Set up in PyDiscovery. To be implemented."""
pass