Skip to content

Commit

Permalink
Added multi-freq & broadband support. Added interpolation settings to…
Browse files Browse the repository at this point in the history
… freq sweep. All under `QHFSSDrivenmodalPyaedt` (#944)

* added interpolation settings to QHFSSDrivenmodalPyaedt.add_sweep

* Added interpolation setting to tutorial

* add_sweep now returns sweep object

* add Multi-Frequency and Broadband setup support

* added documentation for freq and setup methods

* documented solution frequency types to tutorial

* added MaximumPasses support to MultiFreq

---------

Co-authored-by: Zlatko Minev <zminev@gmail.com>
  • Loading branch information
clarkmiyamoto and zlatko-minev authored Jun 14, 2023
1 parent 340dc6e commit 60a9af0
Show file tree
Hide file tree
Showing 2 changed files with 137 additions and 14 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
from qiskit_metal.toolbox_metal.parsing import parse_entry, parse_units
from qiskit_metal import Dict
from typing import List, Tuple, Union
from collections import OrderedDict
import pandas as pd
import pyaedt
from pyaedt import settings
Expand All @@ -18,17 +19,26 @@ class QHFSSDrivenmodalPyaedt(QHFSSPyaedt):

default_setup = Dict(
name="QHFSSDrivenmodalPyaedt_setup",
SolveType='Single',
Frequency="5.0", # GHz
MaxDeltaE="0.01",
MaximumPasses="10",
MinimumPasses="1",
MinimumConvergedPasses="1",
PercentRefinement="30",
BasisOrder="1",
MultipleAdaptiveFreqsSetup=OrderedDict([('1GHz', [0.02]),
('2GHz', [0.02]),
('5GHz', [0.02])]),
BroadbandLowFreq="2", # GHz
BroadbandHighFreq="8", # GHz
)
"""aedt HFSS Options"""
aedt_hfss_drivenmodal_options = Dict()

__supported_SolveType__ = ['Single', 'MultiFrequency', 'Broadband']
"""Supported DrivenModal Solution Types"""

def __init__(self,
multilayer_design: 'MultiPlanar',
project_name: Union[str, None] = None,
Expand Down Expand Up @@ -65,18 +75,25 @@ def __init__(self,
def add_hfss_dm_setup(
self,
name: str = None,
SolveType: str = None,
Frequency: float = None, # GHz
MaxDeltaE: float = None,
MaximumPasses: int = None,
MinimumPasses: int = None,
MinimumConvergedPasses: int = None,
PercentRefinement: int = None,
BasisOrder: int = None):
BasisOrder: int = None,
MultipleAdaptiveFreqsSetup: dict = None,
BroadbandLowFreq: float = None, # GHz
BroadbandHighFreq: float = None # GHz
):
"""Create a solution setup in Ansys HFSS Driven-Modal solution type. If user does not provide
arguments, they will be obtained from QHFSSDrivenmodalPyaedt.default_setup dict.
Args:
name (str, optional): _description_. Defaults to None.
SolveType (str, optional): Solution frequency type. Accepted values are in self.__supported_SolveType__.
Defaults to self.default_setup.
Frequency (float, optional): Minimum frequency in GHz. Defaults to self.default_setup.
MaxDeltaE (float, optional): This is correlated to MaxDeltaS. The definition
of MaxDeltaS is, absolute value of maximum difference in
Expand All @@ -86,7 +103,15 @@ def add_hfss_dm_setup(
MinimumConvergedPasses (int, optional): Minimum number of converged passes. Defaults to self.default_setup.
PercentRefinement (int, optional): Percent refinement. Defaults to self.default_setup.
BasisOrder (int, optional): Basis order. Defaults to self.default_setup.
MultipleAdaptiveFreqsSetup (dict, optional): Frequencies and their associated MaxDeltaS.
Defaults to self.default_setup.
BroadbandLowFreq (float, optional): Minimum frequency for Broadband SolveType in GHz.
Defaults to self.default_setup.
BroadbandHighFreq (float, optional): Maximum frequency for Broadband SolveType in GHz.
Defaults to self.default_setup.
Returns:
new_setup (pyaedt.modules.SolveSetup.SetupHFSS): pyAEDT simulation setup object.
"""

self.activate_user_project_design()
Expand All @@ -105,6 +130,8 @@ def add_hfss_dm_setup(

if not Frequency:
Frequency = float(self.parse_value(dsu['Frequency']))
if not SolveType:
SolveType = str(self.parse_value(dsu['SolveType']))
if not MaxDeltaE:
MaxDeltaE = float(self.parse_value(dsu['MaxDeltaE']))
if not MaximumPasses:
Expand All @@ -118,20 +145,45 @@ def add_hfss_dm_setup(
PercentRefinement = int(self.parse_value(dsu['PercentRefinement']))
if not BasisOrder:
BasisOrder = int(self.parse_value(dsu['BasisOrder']))
if not MultipleAdaptiveFreqsSetup:
MultipleAdaptiveFreqsSetup = dsu['MultipleAdaptiveFreqsSetup']
if not BroadbandLowFreq:
BroadbandLowFreq = float(self.parse_value(dsu['BroadbandLowFreq']))
if not BroadbandHighFreq:
BroadbandHighFreq = float(self.parse_value(
dsu['BroadbandHighFreq']))

new_setup = self.current_app.create_setup(name)

new_setup.props['Frequency'] = f'{Frequency}GHz'
new_setup.props['MaxDeltaE'] = MaxDeltaE
new_setup.props['MaximumPasses'] = MaximumPasses
if (SolveType == 'Single'):
new_setup.props['SolveType'] = 'Single'
new_setup.props['Frequency'] = f'{Frequency}GHz'
new_setup.props['MaximumPasses'] = MaximumPasses
new_setup.props['MaxDeltaE'] = MaxDeltaE
elif (SolveType == 'MultiFrequency'):
new_setup.props['SolveType'] = 'MultiFrequency'
new_setup.props[
'MultipleAdaptiveFreqsSetup'] = MultipleAdaptiveFreqsSetup
new_setup.props['MaximumPasses'] = MaximumPasses
elif (SolveType == 'Broadband'):
new_setup.enable_adaptive_setup_broadband(
low_frequency=f'{BroadbandLowFreq}GHz',
high_frquency=f'{BroadbandHighFreq}GHz',
max_passes=MaximumPasses,
max_delta_s=MaxDeltaE)
else:
raise ValueError(
f'SolveType must be one of the following:{self.__supported_SolveType__}'
)

new_setup.props['MinimumPasses'] = MinimumPasses
new_setup.props['MinimumConvergedPasses'] = MinimumConvergedPasses
new_setup.props['PercentRefinement'] = PercentRefinement
new_setup.props['BasisOrder'] = BasisOrder

new_setup.update()

a = 5
return new_setup

def add_sweep(self,
setup_name="QHFSSDrivenmodalPyaedt_setup",
Expand All @@ -142,7 +194,9 @@ def add_sweep(self,
step_ghz=None,
name="QHFSSDrivenmodalPyaedt_sweep",
type="Fast",
save_fields=False):
save_fields=False,
interpolation_tol=0.5,
interpolation_max_solutions=250):
"""Add a frequency sweep to a driven modal setup.
Args:
Expand All @@ -162,20 +216,31 @@ def add_sweep(self,
and "Discrete". Defaults to "Fast".
save_fields (bool, optional): Whether or not to save fields.
Defaults to False.
interpolation_tol (float, optional): Error tolerance threshold
for the interpolation type sweep. Defaults to 0.5.
interpolation_max_solutions (int, optional): Maximum number of solutions
evaluted for the interpolation process.
Defaults to 250.
Returns:
sweep (pyaedt.modules.SolveSweeps.SweepHFSS): pyAEDT frequency sweep object.
"""

if setup_name in self.current_app.setup_names:

try:
self.current_app.create_linear_count_sweep(
sweep = self.current_app.create_linear_count_sweep(
setupname=setup_name,
unit=unit,
freqstart=start_ghz,
freqstop=stop_ghz,
num_of_freq_points=count,
sweepname=name,
save_fields=save_fields,
sweep_type=type)
sweep_type=type,
interpolation_tol=interpolation_tol,
interpolation_max_solutions=interpolation_max_solutions)
return sweep
except Exception as ex:
self.design.logger.error(f' The exception is {ex}')
else:
Expand All @@ -185,15 +250,18 @@ def add_sweep(self,
)
self.add_hfss_dm_setup(setup_name)
try:
self.current_app.create_linear_count_sweep(
sweep = self.current_app.create_linear_count_sweep(
setupname=setup_name,
unit=unit,
freqstart=start_ghz,
freqstop=stop_ghz,
num_of_freq_points=count,
sweepname=name,
save_fields=save_fields,
sweep_type=type)
sweep_type=type,
interpolation_tol=interpolation_tol,
interpolation_max_solutions=interpolation_max_solutions)
return sweep
except Exception as ex:
self.design.logger.error(f' The exception is {ex}')

Expand Down Expand Up @@ -582,4 +650,4 @@ def create_ports(self, port_list: list, layer_num: int):
a = 5

def add_mesh(self):
a = 5
a = 5
Loading

0 comments on commit 60a9af0

Please sign in to comment.