Source code for ansys.aedt.toolkits.antenna.backend.antenna_models.patch
# -*- coding: utf-8 -*-## Copyright (C) 2023 - 2025 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.fromcollectionsimportOrderedDictimportmathimportansys.aedt.core.generic.constantsasconstantsfromansys.aedt.core.generic.general_methodsimportpyaedt_function_handlerfromansys.aedt.toolkits.common.backend.logger_handlerimportloggerfromansys.aedt.toolkits.antenna.backend.antenna_models.commonimportCommonAntennafromansys.aedt.toolkits.antenna.backend.antenna_models.commonimportTransmissionLineclassCommonPatch(CommonAntenna):"""Provides base methods common to patch antenna."""def__init__(self,_default_input_parameters,*args,**kwargs):CommonAntenna.antenna_type="Patch"CommonAntenna.__init__(self,_default_input_parameters,*args,**kwargs)if"substrate_height"notinkwargs:self.substrate_height=constants.unit_converter(self.substrate_height,"Length",_default_input_parameters["length_unit"],self.length_unit)self._transmission_line_calculator=TransmissionLine(self.frequency,self.frequency_unit)@propertydefmaterial(self):"""Substrate material. Returns ------- str """returnself._input_parameters.material@material.setterdefmaterial(self,value):ifself._app:if(valueandvaluenotinself._app.materials.mat_names_aedtandvaluenotinself._app.materials.mat_names_aedt_lower):logger.debug("Material not defined")else:ifvalue!=self.materialandself.object_list:forantenna_objinself.object_list:if(self.object_list[antenna_obj].material_name==self.material.lower()and"coax"notinantenna_obj):self.object_list[antenna_obj].material_name=valueself._input_parameters.material=valueparameters=self.synthesis()self.update_synthesis_parameters(parameters)self.set_variables_in_hfss()else:self._input_parameters.material=value@propertydefmaterial_properties(self):"""Substrate material properties. Returns ------- str """returnself._input_parameters.material_properties@propertydefsubstrate_height(self):"""Substrate height. Returns ------- float """returnself._input_parameters.substrate_height@substrate_height.setterdefsubstrate_height(self,value):self._input_parameters.substrate_height=valueifself.object_list:parameters=self.synthesis()self.update_synthesis_parameters(parameters)self.set_variables_in_hfss()@pyaedt_function_handler()defsynthesis(self):pass
[docs]classRectangularPatchProbe(CommonPatch):"""Manages a rectangular patch antenna with a coaxial probe. This class is accessible through the ``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 Substrate material. If the material is not defined, a new material, ``parametrized``, is created. The default is ``"FR4_epoxy"``. 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"``. substrate_height : float, optional Substrate height. The default is ``1.575``. parametrized : bool, optional Whether to create a parametrized antenna. The default is ``True``. Returns ------- :class:`aedt.toolkits.antenna.RectangularPatchProbe` Patch antenna object. Notes ----- .. [1] C. Balanis, "Microstrip Antennas," *Antenna Theory*, 2nd Ed. New York: Wiley, 1997. Examples -------- >>> from ansys.aedt.toolkits.antenna.backend.antenna_models.patch import RectangularPatchProbe >>> import ansys.aedt.core >>> app = ansys.aedt.core.Hfss() >>> oantenna1 = RectangularPatchProbe(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":"mm","coordinate_system":"Global","frequency":10.0,"frequency_unit":"GHz","material":"FR4_epoxy","material_properties":{"permittivity":4.4},"outer_boundary":"","substrate_height":1.575,}def__init__(self,*args,**kwargs):CommonPatch.__init__(self,self._default_input_parameters,*args,**kwargs)self._parameters=self.synthesis()self.update_synthesis_parameters(self._parameters)self.antenna_type="RectangularPatchProbe"
[docs]@pyaedt_function_handler()defsynthesis(self):"""Antenna synthesis. Returns ------- dict Analytical parameters. """parameters={}length_unit=self.length_unitlightSpeed=constants.SpeedOfLight# m/sfreq_hz=constants.unit_converter(self.frequency,"Freq",self.frequency_unit,"Hz")wavelength=lightSpeed/freq_hzifself._appand(self.materialinself._app.materials.mat_names_aedtorself.materialinself._app.materials.mat_names_aedt_lower):mat_props=self._app.materials[self.material]permittivity=mat_props.permittivity.valueself._input_parameters.material_properties["permittivity"]=permittivityelifself.material_properties:permittivity=self.material_properties["permittivity"]else:self._app.logger.warning("Material is not found. Create the material before assigning it.")returnparameterssubPermittivity=float(permittivity)sub_meters=constants.unit_converter(self.substrate_height,"Length",self.length_unit,"meter")patch_width=3.0e8/((2.0*freq_hz)*math.sqrt((subPermittivity+1.0)/2.0))eff_Permittivity=(subPermittivity+1.0)/2.0+(subPermittivity-1.0)/2.0*math.pow(1.0+12.0*sub_meters/patch_width,-0.5)effective_length=3.0e8/(2.0*freq_hz*math.sqrt(eff_Permittivity))top=(eff_Permittivity+0.3)*(patch_width/sub_meters+0.264)bottom=(eff_Permittivity-0.258)*(patch_width/sub_meters+0.8)delta_length=0.412*sub_meters*top/bottompatch_length=effective_length-2.0*delta_length# eff_WL_meters = wavelength / math.sqrt(eff_Permittivity)k=2.0*math.pi/eff_PermittivityG=math.pi*patch_width/(120.0*math.pi*wavelength)*(1.0-math.pow(k*sub_meters,2)/24)# impedance at edge of patchRes=1.0/(2.0*G)offset_pin_pos=patch_length/math.pi*math.asin(math.sqrt(50.0/Res))patch_x=constants.unit_converter(patch_width,"Length","meter",length_unit)parameters["patch_x"]=patch_xpatch_y=constants.unit_converter(patch_length,"Length","meter",length_unit)parameters["patch_y"]=patch_yfeed_x=0.0parameters["feed_x"]=feed_xfeed_y=constants.unit_converter(offset_pin_pos,"Length","meter",length_unit)parameters["feed_y"]=feed_ysub_h=self.substrate_heightparameters["sub_h"]=sub_hsub_x=constants.unit_converter(1.5*patch_width+6.0*sub_meters,"Length","meter",length_unit)parameters["sub_x"]=sub_xsub_y=constants.unit_converter(1.5*patch_length+6.0*sub_meters,"Length","meter",length_unit)parameters["sub_y"]=sub_ycoax_inner_rad=constants.unit_converter(0.025*(1e8/freq_hz),"Length","meter",length_unit)parameters["coax_inner_rad"]=coax_inner_radcoax_outer_rad=constants.unit_converter(0.085*(1e8/freq_hz),"Length","meter",length_unit)parameters["coax_outer_rad"]=coax_outer_radfeed_length=constants.unit_converter(wavelength/6.0,"Length","meter",length_unit)parameters["feed_length"]=feed_lengthgnd_x=sub_xgnd_y=sub_yparameters["gnd_x"]=gnd_xparameters["gnd_y"]=gnd_yparameters["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])foriinmyKeys])returnparameters_out
[docs]@pyaedt_function_handler()defmodel_hfss(self):"""Draw rectangular patch antenna with coaxial probe. Once the antenna is created, this method will not be used anymore."""ifself.object_list:logger.debug("This antenna already exists")returnFalseif(self.materialnotinself._app.materials.mat_names_aedtandself.materialnotinself._app.materials.mat_names_aedt_lower):self._app.logger.warning("Material is not found. Create the material before assigning it.")returnFalseself.set_variables_in_hfss()# Map parameterspatch_x=self.synthesis_parameters.patch_x.hfss_variablepatch_y=self.synthesis_parameters.patch_y.hfss_variablefeed_x=self.synthesis_parameters.feed_x.hfss_variablefeed_y=self.synthesis_parameters.feed_y.hfss_variablesub_h=self.synthesis_parameters.sub_h.hfss_variablesub_x=self.synthesis_parameters.sub_x.hfss_variablesub_y=self.synthesis_parameters.sub_y.hfss_variablecoax_inner_rad=self.synthesis_parameters.coax_inner_rad.hfss_variablecoax_outer_rad=self.synthesis_parameters.coax_outer_rad.hfss_variablefeed_length=self.synthesis_parameters.feed_length.hfss_variablegnd_x=self.synthesis_parameters.gnd_x.hfss_variablegnd_y=self.synthesis_parameters.gnd_y.hfss_variablepos_x=self.synthesis_parameters.pos_x.hfss_variablepos_y=self.synthesis_parameters.pos_y.hfss_variablepos_z=self.synthesis_parameters.pos_z.hfss_variableantenna_name=self.namecoordinate_system=self.coordinate_system# Substratesub=self._app.modeler.create_box(origin=["-"+sub_x+"/2","-"+sub_y+"/2","0"],sizes=[sub_x,sub_y,sub_h],name="sub_"+antenna_name,material=self.material,)sub.color=(0,128,0)sub.transparency=0.8sub.history().properties["Coordinate System"]=coordinate_system# Groundgnd=self._app.modeler.create_rectangle(orientation=2,origin=["-"+gnd_x+"/2","-"+gnd_y+"/2","0"],sizes=[gnd_x,gnd_y],name="gnd_"+antenna_name,)gnd.color=(255,128,65)gnd.transparency=0.1gnd.history().properties["Coordinate System"]=coordinate_system# Antennaant=self._app.modeler.create_rectangle(orientation=2,origin=["-"+patch_x+"/2","-"+patch_y+"/2",sub_h,],sizes=[patch_x,patch_y],name="ant_"+antenna_name,)ant.color=(255,128,65)ant.transparency=0.1ant.history().properties["Coordinate System"]=coordinate_systemvoid=self._app.modeler.create_circle(cs_plane=2,origin=[feed_x,feed_y,"0"],radius=coax_outer_rad,name="void_"+antenna_name,)self._app.modeler.subtract(gnd,void,False)feed_pin=self._app.modeler.create_cylinder(orientation=2,origin=[feed_x,feed_y,"0"],radius=coax_inner_rad,height=sub_h,name="feed_pin_"+antenna_name,material="pec",)feed_pin.color=(255,128,65)feed_pin.history().properties["Coordinate System"]=coordinate_systemfeed_coax=self._app.modeler.create_cylinder(orientation=2,origin=[feed_x,feed_y,"0"],radius=coax_inner_rad,height="-"+feed_length,name="feed_coax_"+antenna_name,material="pec",)feed_coax.color=(255,128,65)feed_coax.history().properties["Coordinate System"]=coordinate_systemcoax=self._app.modeler.create_cylinder(orientation=2,origin=[feed_x,feed_y,"0"],radius=coax_outer_rad,height="-"+feed_length,name="coax_"+antenna_name,material="Teflon (tm)",)coax.color=(128,255,255)coax.history().properties["Coordinate System"]=coordinate_systemport_cap=self._app.modeler.create_cylinder(orientation=2,origin=[feed_x,feed_y,"-"+feed_length],radius=coax_outer_rad,height="-"+sub_h+"/"+str(10),name="port_cap_"+antenna_name,material="pec",)port_cap.color=(132,132,193)port_cap.history().properties["Coordinate System"]=coordinate_systemp1=self._app.modeler.create_circle(cs_plane=2,origin=[feed_x,feed_y,"-"+feed_length],radius=coax_outer_rad,name="port_"+antenna_name,)p1.color=(128,0,0)p1.history().properties["Coordinate System"]=coordinate_systemself.object_list[sub.name]=subself.object_list[gnd.name]=gndself.object_list[ant.name]=antself.object_list[feed_pin.name]=feed_pinself.object_list[feed_coax.name]=feed_coaxself.object_list[coax.name]=coaxself.object_list[port_cap.name]=port_capself.object_list[p1.name]=p1self._app.modeler.move(list(self.object_list.keys()),[pos_x,pos_y,pos_z])sub.group_name=antenna_namegnd.group_name=antenna_nameant.group_name=antenna_namefeed_pin.group_name=antenna_namefeed_coax.group_name=antenna_namecoax.group_name=antenna_nameport_cap.group_name=antenna_namep1.group_name=antenna_name
[docs]@pyaedt_function_handler()defmodel_disco(self):"""Model in PyDiscovery. To be implemented."""pass
[docs]@pyaedt_function_handler()defsetup_disco(self):"""Set up the model in PyDiscovery. To be implemented."""pass
[docs]classRectangularPatchInset(CommonPatch):"""Manages a rectangular patch antenna inset fed. This class is accessible through the ``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 Substrate material. If the material is not defined, a new material, ``parametrized``, is created. The default is ``"FR4_epoxy"``. 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"``. substrate_height : float, optional Substrate height. The default is ``1.575``. parametrized : bool, optional Whether to create a parametrized antenna. The default is ``True``. Returns ------- :class:`aedt.toolkits.antenna.RectangularPatchInset` Patch antenna object. Notes ----- .. [1] C. Balanis, "Microstrip Antennas," *Antenna Theory*, 2nd Ed. New York: Wiley, 1997. Examples -------- >>> from ansys.aedt.toolkits.antenna.backend.antenna_models.patch import RectangularPatchInset >>> import ansys.aedt.core >>> app = ansys.aedt.core.Hfss() >>> oantenna1 = RectangularPatchInset(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":"mm","coordinate_system":"Global","frequency":10.0,"frequency_unit":"GHz","material":"FR4_epoxy","material_properties":{"permittivity":4.4},"outer_boundary":"","substrate_height":1.575,}def__init__(self,*args,**kwargs):CommonPatch.__init__(self,self._default_input_parameters,*args,**kwargs)self._parameters=self.synthesis()self.update_synthesis_parameters(self._parameters)self.antenna_type="RectangularPatchInset"
[docs]@pyaedt_function_handler()defsynthesis(self):"""Antenna synthesis. Returns ------- dict Analytical parameters. """parameters={}length_unit=self.length_unitlightSpeed=constants.SpeedOfLight# m/sfreq_hz=constants.unit_converter(self.frequency,"Freq",self.frequency_unit,"Hz")wavelength=lightSpeed/freq_hzifself._appand(self.materialinself._app.materials.mat_names_aedtorself.materialinself._app.materials.mat_names_aedt_lower):mat_props=self._app.materials[self.material]permittivity=mat_props.permittivity.valueself._input_parameters.material_properties["permittivity"]=permittivityelifself.material_properties:permittivity=self.material_properties["permittivity"]else:self._app.logger.warning("Material is not found. Create the material before assigning it.")returnparameterssubPermittivity=float(permittivity)patch_width=3.0e8/((2.0*freq_hz)*math.sqrt((subPermittivity+1.0)/2.0))sub_meters=constants.unit_converter(self.substrate_height,"Length",self.length_unit,"meter")eff_Permittivity=(subPermittivity+1.0)/2.0+(subPermittivity-1.0)/2.0*math.pow(1.0+12.0*sub_meters/patch_width,-0.5)effective_length=3.0e8/(2.0*freq_hz*math.sqrt(eff_Permittivity))top=(eff_Permittivity+0.3)*(patch_width/sub_meters+0.264)bottom=(eff_Permittivity-0.258)*(patch_width/sub_meters+0.8)delta_length=0.412*sub_meters*top/bottompatch_length=effective_length-2.0*delta_length# eff_WL_meters = wavelength / math.sqrt(eff_Permittivity)k=2.0*math.pi/eff_PermittivityG=math.pi*patch_width/(120.0*math.pi*wavelength)*(1.0-math.pow(k*sub_meters,2)/24)# impedance at edge of patchRes=1.0/(2.0*G)inset_distance_meter=patch_length/math.pi*math.asin(math.sqrt(50.0/Res))# quarterwave_imped = math.sqrt(50.0 * Res)uStrip=self._transmission_line_calculator.microstrip_calculator(sub_meters,subPermittivity,50.0,150.0)microstrip_width=uStrip[0]microstrip_length=uStrip[1]patch_x=constants.unit_converter(patch_width,"Length","meter",length_unit)parameters["patch_x"]=patch_xpatch_y=constants.unit_converter(patch_length,"Length","meter",length_unit)parameters["patch_y"]=patch_ysub_h=self.substrate_heightparameters["sub_h"]=sub_hsub_x=constants.unit_converter(1.5*patch_width+6.0*sub_meters,"Length","meter",length_unit)parameters["sub_x"]=sub_xsub_y=constants.unit_converter(2.1*(microstrip_length+patch_length/2),"Length","meter",length_unit)parameters["sub_y"]=sub_yinset_distance=constants.unit_converter(patch_length/2-inset_distance_meter,"Length","meter",length_unit)parameters["inset_distance"]=inset_distancemicrostrip_length=constants.unit_converter(microstrip_length,"Length","meter",length_unit)microstrip_width=constants.unit_converter(microstrip_width,"Length","meter",length_unit)inset_gap=round(microstrip_width/2,3)parameters["inset_gap"]=inset_gapfeed_width=round(microstrip_width,3)parameters["feed_width"]=feed_widthfeed_length=round(microstrip_length,3)parameters["feed_length"]=feed_lengthparameters["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])foriinmyKeys])returnparameters_out
[docs]@pyaedt_function_handler()defmodel_hfss(self):"""Draw a rectangular patch antenna inset fed. Once the antenna is created, this method is not used anymore."""ifself.object_list:self._app.logger.warning("This antenna already exists.")returnFalseif(self.materialnotinself._app.materials.mat_names_aedtandself.materialnotinself._app.materials.mat_names_aedt_lower):self._app.logger.warning("Material is not found. Create the material before assigning it.")returnFalseself.set_variables_in_hfss()# Map parameterspatch_x=self.synthesis_parameters.patch_x.hfss_variablepatch_y=self.synthesis_parameters.patch_y.hfss_variablesub_h=self.synthesis_parameters.sub_h.hfss_variablesub_x=self.synthesis_parameters.sub_x.hfss_variablesub_y=self.synthesis_parameters.sub_y.hfss_variableinset_distance=self.synthesis_parameters.inset_distance.hfss_variableinset_gap=self.synthesis_parameters.inset_gap.hfss_variablefeed_width=self.synthesis_parameters.feed_width.hfss_variablefeed_length=self.synthesis_parameters.feed_length.hfss_variablepos_x=self.synthesis_parameters.pos_x.hfss_variablepos_y=self.synthesis_parameters.pos_y.hfss_variablepos_z=self.synthesis_parameters.pos_z.hfss_variableantenna_name=self.namecoordinate_system=self.coordinate_system# Substratesub=self._app.modeler.create_box(origin=["-"+sub_x+"/2","-"+sub_y+"/2","0"],sizes=[sub_x,sub_y,sub_h],name="sub_"+antenna_name,material=self.material,)sub.color=(0,128,0)sub.transparency=0.8sub.history().properties["Coordinate System"]=coordinate_system# Groundgnd=self._app.modeler.create_rectangle(orientation=2,origin=["-"+sub_x+"/2","-"+sub_y+"/2","0"],sizes=[sub_x,sub_y],name="gnd_"+antenna_name,)gnd.color=(255,128,65)gnd.transparency=0.1gnd.history().properties["Coordinate System"]=coordinate_system# Antennaant=self._app.modeler.create_rectangle(orientation=2,origin=["-"+patch_x+"/2","-"+patch_y+"/2",sub_h,],sizes=[patch_x,patch_y],name="ant_"+antenna_name,)ant.color=(255,128,65)ant.transparency=0.1ant.history().properties["Coordinate System"]=coordinate_systemcutout=self._app.modeler.create_rectangle(orientation=2,origin=["-"+feed_width+"/2"+"-"+inset_gap,patch_y+"/2"+"-"+inset_distance,sub_h,],sizes=[feed_width+"+2*"+inset_gap,feed_length],name="cutout_"+antenna_name,)cutout.color=(255,128,65)cutout.history().properties["Coordinate System"]=coordinate_systemself._app.modeler.subtract(ant,cutout,False)feed=self._app.modeler.create_rectangle(orientation=2,origin=["-"+feed_width+"/2",patch_y+"/2""-"+inset_distance,sub_h,],sizes=[feed_width,feed_length+"+"+inset_distance],name="feed_"+antenna_name,)feed.color=(255,128,65)feed.history().properties["Coordinate System"]=coordinate_systemself._app.modeler.unite([ant,feed])p1=self._app.modeler.create_rectangle(orientation=1,origin=["-"+feed_width+"/2",patch_y+"/2"+"+"+feed_length,"0",],sizes=[sub_h,feed_width],name="port_lump_"+antenna_name,)p1.color=(255,128,65)p1.history().properties["Coordinate System"]=coordinate_systemself.object_list[sub.name]=subself.object_list[gnd.name]=gndself.object_list[ant.name]=antself.object_list[p1.name]=p1self._app.modeler.move(list(self.object_list.keys()),[pos_x,pos_y,pos_z])sub.group_name=antenna_namegnd.group_name=antenna_nameant.group_name=antenna_namep1.group_name=antenna_name
[docs]@pyaedt_function_handler()defmodel_disco(self):"""Model in PyDiscovery. To be implemented."""pass
[docs]@pyaedt_function_handler()defsetup_disco(self):"""Set up the model in PyDiscovery. To be implemented."""pass
[docs]classRectangularPatchEdge(CommonPatch):"""Manages a rectangular patch edge antenna. This class is accessible through the ``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 Substrate material. If the material is not defined, a new material, ``parametrized``, is created. The default is ``"FR4_epoxy"``. 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"``. substrate_height : float, optional Substrate height. The default is ``1.575``. parametrized : bool, optional Whether to create a parametrized antenna. The default is ``True``. Returns ------- :class:`aedt.toolkits.antenna.RectangularPatchEdge` Patch antenna object. Notes ----- .. [1] C. Balanis, "Microstrip Antennas," *Antenna Theory*, 2nd Ed. New York: Wiley, 1997. Examples -------- >>> from ansys.aedt.toolkits.antenna.backend.antenna_models.patch import RectangularPatchEdge >>> import ansys.aedt.core >>> app = ansys.aedt.core.Hfss() >>> oantenna1 = RectangularPatchEdge(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":"mm","coordinate_system":"Global","frequency":10.0,"frequency_unit":"GHz","material":"FR4_epoxy","material_properties":{"permittivity":4.4},"outer_boundary":"","substrate_height":1.575,}def__init__(self,*args,**kwargs):CommonPatch.__init__(self,self._default_input_parameters,*args,**kwargs)self._parameters=self.synthesis()self.update_synthesis_parameters(self._parameters)self.antenna_type="RectangularPatchEdge"
[docs]@pyaedt_function_handler()defsynthesis(self):"""Antenna synthesis. Returns ------- dict Analytical parameters. """parameters={}length_unit=self.length_unitlightSpeed=constants.SpeedOfLight# m/sfreq_hz=constants.unit_converter(self.frequency,"Freq",self.frequency_unit,"Hz")wavelength=lightSpeed/freq_hzifself._appand(self.materialinself._app.materials.mat_names_aedtorself.materialinself._app.materials.mat_names_aedt_lower):mat_props=self._app.materials[self.material]permittivity=mat_props.permittivity.valueself._input_parameters.material_properties["permittivity"]=permittivityelifself.material_properties:permittivity=self.material_properties["permittivity"]else:self._app.logger.warning("Material is not found. Create the material before assigning it.")returnparameterssubPermittivity=float(permittivity)patch_width=3.0e8/((2.0*freq_hz)*math.sqrt((subPermittivity+1.0)/2.0))sub_meters=constants.unit_converter(self.substrate_height,"Length",self.length_unit,"meter")eff_Permittivity=(subPermittivity+1.0)/2.0+(subPermittivity-1.0)/2.0*math.pow(1.0+12.0*sub_meters/patch_width,-0.5)effective_length=3.0e8/(2.0*freq_hz*math.sqrt(eff_Permittivity))top=(eff_Permittivity+0.3)*(patch_width/sub_meters+0.264)bottom=(eff_Permittivity-0.258)*(patch_width/sub_meters+0.8)delta_length=0.412*sub_meters*top/bottompatch_length=effective_length-2.0*delta_length# eff_WL_meters = wavelength / math.sqrt(eff_Permittivity)k=2.0*math.pi/eff_PermittivityG=math.pi*patch_width/(120.0*math.pi*wavelength)*(1.0-math.pow(k*sub_meters,2)/24)# impedance at edge of patchRes=1.0/(2.0*G)# offset_pin_pos = patch_length / math.pi * math.asin(math.sqrt(50.0 / Res))quarterwave_imped=math.sqrt(50.0*Res)uStrip1=self._transmission_line_calculator.microstrip_calculator(sub_meters,subPermittivity,quarterwave_imped,90.0)microstrip_edge_width=uStrip1[0]microstrip_edge_length=uStrip1[1]uStrip2=self._transmission_line_calculator.microstrip_calculator(sub_meters,subPermittivity,50.0,150.0)microstrip_width=uStrip2[0]microstrip_length=uStrip2[1]patch_x=constants.unit_converter(patch_width,"Length","meter",length_unit)parameters["patch_x"]=patch_xpatch_y=constants.unit_converter(patch_length,"Length","meter",length_unit)parameters["patch_y"]=patch_ysub_h=self.substrate_heightparameters["sub_h"]=sub_hsub_x=constants.unit_converter(1.5*patch_width+6.0*sub_meters,"Length","meter",length_unit)parameters["sub_x"]=sub_xsub_y=constants.unit_converter(2.1*(microstrip_length+microstrip_edge_length+patch_length/2),"Length","meter",length_unit,)parameters["sub_y"]=sub_yedge_feed_width=constants.unit_converter(microstrip_edge_width,"Length","meter",length_unit)parameters["edge_feed_width"]=edge_feed_widthedge_feed_length=constants.unit_converter(microstrip_edge_length,"Length","meter",length_unit)parameters["edge_feed_length"]=edge_feed_lengthfeed_width=constants.unit_converter(microstrip_width,"Length","meter",length_unit)parameters["feed_width"]=feed_widthfeed_length=constants.unit_converter(microstrip_length,"Length","meter",length_unit)parameters["feed_length"]=feed_lengthparameters["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])foriinmyKeys])returnparameters_out
[docs]@pyaedt_function_handler()defmodel_hfss(self):"""Draw a rectangular patch edge antenna inset fed. Once the antenna is created, this method is not used anymore."""ifself.object_list:self._app.logger.warning("This antenna already exists.")returnFalseif(self.materialnotinself._app.materials.mat_names_aedtandself.materialnotinself._app.materials.mat_names_aedt_lower):self._app.logger.warning("Material is not found. Create the material before assigning it.")returnFalseself.set_variables_in_hfss()# Map parameterspatch_x=self.synthesis_parameters.patch_x.hfss_variablepatch_y=self.synthesis_parameters.patch_y.hfss_variablesub_h=self.synthesis_parameters.sub_h.hfss_variablesub_x=self.synthesis_parameters.sub_x.hfss_variablesub_y=self.synthesis_parameters.sub_y.hfss_variableedge_feed_width=self.synthesis_parameters.edge_feed_width.hfss_variableedge_feed_length=self.synthesis_parameters.edge_feed_length.hfss_variablefeed_width=self.synthesis_parameters.feed_width.hfss_variablefeed_length=self.synthesis_parameters.feed_length.hfss_variablepos_x=self.synthesis_parameters.pos_x.hfss_variablepos_y=self.synthesis_parameters.pos_y.hfss_variablepos_z=self.synthesis_parameters.pos_z.hfss_variableantenna_name=self.namecoordinate_system=self.coordinate_system# Substratesub=self._app.modeler.create_box(origin=["-"+sub_x+"/2","-"+sub_y+"/2","0"],sizes=[sub_x,sub_y,sub_h],name="sub_"+antenna_name,material=self.material,)sub.color=(0,128,0)sub.transparency=0.8sub.history().properties["Coordinate System"]=coordinate_system# Groundgnd=self._app.modeler.create_rectangle(orientation=2,origin=["-"+sub_x+"/2","-"+sub_y+"/2","0"],sizes=[sub_x,sub_y],name="gnd_"+antenna_name,)gnd.color=(255,128,65)gnd.transparency=0.1gnd.history().properties["Coordinate System"]=coordinate_system# Antennaant=self._app.modeler.create_rectangle(orientation=2,origin=["-"+patch_x+"/2","-"+patch_y+"/2",sub_h,],sizes=[patch_x,patch_y],name="ant_"+antenna_name,)ant.color=(255,128,65)ant.transparency=0.1ant.history().properties["Coordinate System"]=coordinate_systemedge_feed=self._app.modeler.create_rectangle(orientation=2,origin=["-"+edge_feed_width+"/2","0",sub_h,],sizes=[edge_feed_width,patch_y+"/2"+"+"+edge_feed_length],name="cutout_"+antenna_name,)edge_feed.color=(255,128,65)edge_feed.history().properties["Coordinate System"]=coordinate_systemfeed=self._app.modeler.create_rectangle(orientation=2,origin=["-"+feed_width+"/2",patch_y+"/2"+"+"+edge_feed_length,sub_h,],sizes=[feed_width,feed_length],name="feed_"+antenna_name,)feed.color=(255,128,65)feed.history().properties["Coordinate System"]=coordinate_systemself._app.modeler.unite([ant,edge_feed,feed])p1=self._app.modeler.create_rectangle(orientation=1,origin=["-"+feed_width+"/2",patch_y+"/2"+"+"+edge_feed_length+"+"+feed_length,"0",],sizes=[sub_h,feed_width],name="port_lump_"+antenna_name,)p1.color=(255,128,65)p1.history().properties["Coordinate System"]=coordinate_systemself.object_list[sub.name]=subself.object_list[gnd.name]=gndself.object_list[ant.name]=antself.object_list[p1.name]=p1self._app.modeler.move(list(self.object_list.keys()),[pos_x,pos_y,pos_z])sub.group_name=antenna_namegnd.group_name=antenna_nameant.group_name=antenna_namep1.group_name=antenna_name
[docs]@pyaedt_function_handler()defmodel_disco(self):"""Model in PyDiscovery. To be implemented."""pass
[docs]@pyaedt_function_handler()defsetup_disco(self):"""Set up the model in PyDiscovery. To be implemented."""pass