diff --git a/doc/changelog.d/1659.miscellaneous.md b/doc/changelog.d/1659.miscellaneous.md new file mode 100644 index 0000000000..39c7b754cd --- /dev/null +++ b/doc/changelog.d/1659.miscellaneous.md @@ -0,0 +1 @@ +Edb cfg boundaries diff --git a/src/pyedb/configuration/cfg_boundaries.py b/src/pyedb/configuration/cfg_boundaries.py index 3835be8d8b..8c56e1d963 100644 --- a/src/pyedb/configuration/cfg_boundaries.py +++ b/src/pyedb/configuration/cfg_boundaries.py @@ -19,87 +19,43 @@ # 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 typing import Any, Optional, Union -from pyedb.configuration.cfg_common import CfgBase +from pydantic import BaseModel, Field -class CfgBoundaries(CfgBase): - def __init__(self, pedb, boundary_data): - self._pedb = pedb - self.boundary_data = boundary_data - - self.open_region = self.boundary_data.get("open_region", None) - self.open_region_type = self.boundary_data.get("map_open_region_type", None) - self.pml_visible = self.boundary_data.get("pml_visible", None) - self.pml_operation_frequency = self.boundary_data.get("pml_operation_frequency", None) - self.pml_radiation_factor = self.boundary_data.get("pml_radiation_factor", None) - self.dielectric_extent_type = self.boundary_data.get("dielectric_extent_type", None) - self.horizontal_padding = self.boundary_data.get("horizontal_padding", None) - self.honor_primitives_on_dielectric_layers = self.boundary_data.get( - "honor_primitives_on_dielectric_layers", False - ) - self.air_box_extent_type = self.boundary_data.get("air_box_extent_type", None) - self.air_box_base_polygon = self.boundary_data.get("air_box_base_polygon", None) - self.air_box_truncate_model_ground_layers = self.boundary_data.get("air_box_truncate_model_ground_layers", None) - self.air_box_horizontal_padding = self.boundary_data.get("air_box_horizontal_padding", None) - self.air_box_positive_vertical_padding = self.boundary_data.get("air_box_positive_vertical_padding", None) - self.air_box_negative_vertical_padding = self.boundary_data.get("air_box_negative_vertical_padding", None) +class CfgBase(BaseModel): + model_config = { + "populate_by_name": True, + "extra": "forbid", + } - def get_parameters_from_edb(self): - self.open_region = self._pedb.hfss.hfss_extent_info.use_open_region - self.open_region_type = self._pedb.hfss.hfss_extent_info.open_region_type - self.pml_visible = self._pedb.hfss.hfss_extent_info.is_pml_visible - self.pml_operation_frequency = self._pedb.hfss.hfss_extent_info.operating_freq.tostring - self.pml_radiation_factor = self._pedb.hfss.hfss_extent_info.radiation_level.tostring - self.dielectric_extent_type = self._pedb.hfss.hfss_extent_info.extent_type - self.horizontal_padding = self._pedb.hfss.hfss_extent_info.dielectric_extent_size - self.honor_primitives_on_dielectric_layers = self._pedb.hfss.hfss_extent_info.honor_user_dielectric - self.air_box_extent_type = self._pedb.hfss.hfss_extent_info.extent_type - self.air_box_truncate_model_ground_layers = self._pedb.hfss.hfss_extent_info.truncate_air_box_at_ground - self.air_box_horizontal_padding = self._pedb.hfss.hfss_extent_info.air_box_horizontal_extent - self.air_box_positive_vertical_padding = self._pedb.hfss.hfss_extent_info.air_box_positive_vertical_extent - self.air_box_negative_vertical_padding = self._pedb.hfss.hfss_extent_info.air_box_negative_vertical_extent - return self.get_attributes(exclude="boundary_data") - def set_parameters_to_edb(self): - """Imports boundary information from JSON.""" - if self.open_region is not None: - self._pedb.hfss.hfss_extent_info.use_open_region = self.open_region - if self.open_region_type: - self._pedb.hfss.hfss_extent_info.open_region_type = self.open_region_type.lower() - if self.pml_visible is not None: - self._pedb.hfss.hfss_extent_info.is_pml_visible = self.pml_visible - if self.pml_operation_frequency: - self._pedb.hfss.hfss_extent_info.operating_freq = self.pml_operation_frequency - if self.pml_radiation_factor: - if self._pedb.grpc: - self._pedb.hfss.hfss_extent_info.pml_radiation_factor = self.pml_radiation_factor - else: - self._pedb.hfss.hfss_extent_info.radiation_level = self.pml_radiation_factor - if self.dielectric_extent_type: - self._pedb.hfss.hfss_extent_info.extent_type = self.dielectric_extent_type.lower() - if self.horizontal_padding: - self._pedb.hfss.hfss_extent_info.dielectric_extent_size = float(self.horizontal_padding) - if self.honor_primitives_on_dielectric_layers is not None: - self._pedb.hfss.hfss_extent_info.honor_user_dielectric = self.honor_primitives_on_dielectric_layers - if self.air_box_extent_type: - self._pedb.hfss.hfss_extent_info.extent_type = self.air_box_extent_type.lower() - if self.air_box_truncate_model_ground_layers is not None: - self._pedb.hfss.hfss_extent_info.truncate_air_box_at_ground = self.air_box_truncate_model_ground_layers - if self.air_box_horizontal_padding: - self._pedb.hfss.hfss_extent_info.air_box_horizontal_extent = float(self.air_box_horizontal_padding) - if self.air_box_positive_vertical_padding: - self._pedb.hfss.hfss_extent_info.air_box_positive_vertical_extent = float( - self.air_box_positive_vertical_padding - ) - if self.air_box_negative_vertical_padding: - self._pedb.hfss.hfss_extent_info.air_box_negative_vertical_extent = float( - self.air_box_negative_vertical_padding - ) +class PaddingData(CfgBase): + size: Union[float, str] + is_multiple: bool - def apply(self): - """Imports boundary information from JSON.""" - self.set_parameters_to_edb() - def get_data_from_db(self): - return self.get_parameters_from_edb() +class CfgBoundaries(CfgBase): + use_open_region: Optional[Any] = Field(default=None) + open_region_type: Optional[Any] = Field(default=None) + is_pml_visible: Optional[Any] = Field(default=None) + operating_freq: Optional[Any] = Field(default=None) + pml_radiation_factor: Optional[int] = Field(default=None) + + dielectric_extent_type: Optional[str] = Field(default=None) + dielectric_base_polygon: Optional[str] = Field(default=None) + dielectric_extent_size: Optional[PaddingData] = Field(default=None) + honor_user_dielectric: bool = Field(default=False) + + extent_type: Optional[Any] = Field(default=None) + base_polygon: Optional[Any] = Field(default=None) + truncate_air_box_at_ground: Optional[Any] = Field(default=None) + air_box_horizontal_extent: Optional[PaddingData] = Field(default=None) + air_box_positive_vertical_extent: Optional[PaddingData] = Field(default=None) + air_box_negative_vertical_extent: Optional[PaddingData] = Field(default=None) + sync_air_box_vertical_extent: Optional[bool] = Field(default=None) + + @classmethod + def create(cls, **kwargs): + return cls(**kwargs) diff --git a/src/pyedb/configuration/cfg_data.py b/src/pyedb/configuration/cfg_data.py index 4840d5582d..3f08cfffb8 100644 --- a/src/pyedb/configuration/cfg_data.py +++ b/src/pyedb/configuration/cfg_data.py @@ -46,7 +46,7 @@ def __init__(self, pedb, **kwargs): self._pedb = pedb self.general = CfgGeneral(self._pedb, kwargs.get("general", {})) - self.boundaries = CfgBoundaries(self._pedb, kwargs.get("boundaries", {})) + self.boundaries = CfgBoundaries.create(**kwargs.get("boundaries", {})) self.nets = CfgNets( self._pedb, diff --git a/src/pyedb/configuration/configuration.py b/src/pyedb/configuration/configuration.py index 523968ed69..ce22f34ee1 100644 --- a/src/pyedb/configuration/configuration.py +++ b/src/pyedb/configuration/configuration.py @@ -122,9 +122,7 @@ def run(self, **kwargs): if self.cfg_data.general: self.cfg_data.general.apply() - # Configure boundary settings - if self.cfg_data.boundaries: - self.__apply_with_logging("Updating boundaries", self.cfg_data.boundaries.apply) + self.apply_boundaries() if self.cfg_data.nets: self.__apply_with_logging("Updating nets", self.cfg_data.nets.apply) @@ -154,6 +152,75 @@ def run(self, **kwargs): return True + def apply_boundaries(self): + boundaries = self.cfg_data.boundaries + info = self._pedb.hfss.hfss_extent_info + + # Simple direct-assign attributes: + attr_map = { + "use_open_region": "use_open_region", + "open_region_type": "open_region_type", + "is_pml_visible": "is_pml_visible", + "operating_freq": "operating_freq", + "pml_radiation_factor": "pml_radiation_factor", + "dielectric_extent_type": "dielectric_extent_type", + "honor_user_dielectric": "honor_user_dielectric", + "extent_type": "extent_type", + "truncate_air_box_at_ground": "truncate_air_box_at_ground", + "base_polygon": "base_polygon", + "dielectric_base_polygon": "dielectric_base_polygon", + "sync_air_box_vertical_extent": "sync_air_box_vertical_extent", + } + + for b_attr, info_attr in attr_map.items(): + value = getattr(boundaries, b_attr, None) + if value is not None: + # Lowercase only string-based HFSS enum-like values + if b_attr in ("open_region_type", "dielectric_extent_type", "extent_type") and isinstance(value, str): + value = value.lower() + if hasattr(info, info_attr): + setattr(info, info_attr, value) + else: # pragma: no cover + raise AttributeError(f"Attribute {info_attr} not found in {info.__name__}") + + # Attributes requiring specific setter functions + if boundaries.dielectric_extent_size: + info.set_dielectric_extent(**boundaries.dielectric_extent_size.model_dump()) + + if boundaries.air_box_horizontal_extent: + info.set_air_box_horizontal_extent(**boundaries.air_box_horizontal_extent.model_dump()) + + if boundaries.air_box_positive_vertical_extent: + info.set_air_box_positive_vertical_extent(**boundaries.air_box_positive_vertical_extent.model_dump()) + + if boundaries.air_box_negative_vertical_extent: + info.set_air_box_negative_vertical_extent(**boundaries.air_box_negative_vertical_extent.model_dump()) + + def get_boundaries(self): + boundaries = self.cfg_data.boundaries + edb_hfss_extent_info = self._pedb.hfss.hfss_extent_info + + boundaries.use_open_region = edb_hfss_extent_info.use_open_region + boundaries.open_region_type = edb_hfss_extent_info.open_region_type + boundaries.is_pml_visible = edb_hfss_extent_info.is_pml_visible + boundaries.operating_freq = edb_hfss_extent_info.operating_freq + boundaries.pml_radiation_factor = edb_hfss_extent_info.pml_radiation_factor + boundaries.dielectric_extent_type = edb_hfss_extent_info.dielectric_extent_type + size, is_multiple = edb_hfss_extent_info.get_dielectric_extent() + boundaries.dielectric_extent_size = {"size": size, "is_multiple": is_multiple} + boundaries.honor_user_dielectric = edb_hfss_extent_info.honor_user_dielectric + boundaries.extent_type = edb_hfss_extent_info.extent_type + boundaries.truncate_air_box_at_ground = edb_hfss_extent_info.truncate_air_box_at_ground + size, is_multiple = edb_hfss_extent_info.get_air_box_horizontal_extent() + boundaries.air_box_horizontal_extent = {"size": size, "is_multiple": is_multiple} + size, is_multiple = edb_hfss_extent_info.get_air_box_positive_vertical_extent() + boundaries.air_box_positive_vertical_extent = {"size": size, "is_multiple": is_multiple} + size, is_multiple = edb_hfss_extent_info.get_air_box_negative_vertical_extent() + boundaries.air_box_negative_vertical_extent = {"size": size, "is_multiple": is_multiple} + boundaries.base_polygon = edb_hfss_extent_info.base_polygon + boundaries.dielectric_base_polygon = edb_hfss_extent_info.dielectric_base_polygon + boundaries.sync_air_box_vertical_extent = edb_hfss_extent_info.sync_air_box_vertical_extent + def apply_modeler(self): modeler = self.cfg_data.modeler if modeler.traces: @@ -419,17 +486,17 @@ def get_data_from_db(self, **kwargs): """ self._pedb.logger.info("Getting data from layout database.") - self.get_variables() + self.get_materials() - self.get_stackup() - self.get_operations() data = {} if kwargs.get("general", False): data["general"] = self.cfg_data.general.get_data_from_db() if kwargs.get("variables", False): + self.get_variables() data.update(self.cfg_data.variables.model_dump(exclude_none=True)) if kwargs.get("stackup", False): + self.get_stackup() data["stackup"] = self.cfg_data.stackup.model_dump(exclude_none=True) if kwargs.get("package_definitions", False): data["package_definitions"] = self.cfg_data.package_definitions.get_data_from_db() @@ -461,6 +528,7 @@ def get_data_from_db(self, **kwargs): if kwargs.get("pin_groups", False): data["pin_groups"] = self.cfg_data.pin_groups.get_data_from_db() if kwargs.get("operations", False): + self.get_operations() data["operations"] = self.cfg_data.operations.model_dump() if kwargs.get("padstacks", False): self.cfg_data.padstacks.retrieve_parameters_from_edb() @@ -475,8 +543,8 @@ def get_data_from_db(self, **kwargs): data["padstacks"]["instances"] = instances if kwargs.get("boundaries", False): - data["boundaries"] = self.cfg_data.boundaries.get_data_from_db() - + self.get_boundaries() + data["boundaries"] = self.cfg_data.boundaries.model_dump(exclude_none=True) return data @execution_timer("Applying operations") diff --git a/src/pyedb/dotnet/database/edb_data/hfss_extent_info.py b/src/pyedb/dotnet/database/edb_data/hfss_extent_info.py index cf0fda80de..e5dc778ab0 100644 --- a/src/pyedb/dotnet/database/edb_data/hfss_extent_info.py +++ b/src/pyedb/dotnet/database/edb_data/hfss_extent_info.py @@ -23,6 +23,7 @@ from pyedb.dotnet.database.edb_data.edbvalue import EdbValue from pyedb.dotnet.database.edb_data.primitives_data import cast from pyedb.dotnet.database.general import convert_pytuple_to_nettuple, pascal_to_snake +from pyedb.dotnet.database.utilities.value import Value class HfssExtentInfo: @@ -85,6 +86,15 @@ def air_box_horizontal_extent(self, value): info.AirBoxHorizontalExtent = convert_pytuple_to_nettuple((value, self.air_box_horizontal_extent_enabled)) self._update_hfss_extent_info(info) + def set_air_box_horizontal_extent(self, size: float, is_multiple: bool = True): + info = self._edb_hfss_extent_info + info.AirBoxHorizontalExtent = convert_pytuple_to_nettuple((size, is_multiple)) + self._update_hfss_extent_info(info) + + def get_air_box_horizontal_extent(self): + info = self._edb_hfss_extent_info + return info.AirBoxHorizontalExtent.Item1, info.AirBoxHorizontalExtent.Item2 + @property def air_box_positive_vertical_extent_enabled(self): """Whether positive vertical extent is enabled for the air box.""" @@ -110,6 +120,15 @@ def air_box_positive_vertical_extent(self, value): ) self._update_hfss_extent_info(info) + def set_air_box_positive_vertical_extent(self, size: float, is_multiple: bool = True): + info = self._edb_hfss_extent_info + info.AirBoxPositiveVerticalExtent = convert_pytuple_to_nettuple((size, is_multiple)) + self._update_hfss_extent_info(info) + + def get_air_box_positive_vertical_extent(self): + info = self._edb_hfss_extent_info + return info.AirBoxPositiveVerticalExtent.Item1, info.AirBoxPositiveVerticalExtent.Item2 + @property def air_box_negative_vertical_extent_enabled(self): """Whether negative vertical extent is enabled for the air box.""" @@ -135,6 +154,15 @@ def air_box_negative_vertical_extent(self, value): ) self._update_hfss_extent_info(info) + def set_air_box_negative_vertical_extent(self, size: float, is_multiple: bool = True): + info = self._edb_hfss_extent_info + info.AirBoxNegativeVerticalExtent = convert_pytuple_to_nettuple((size, is_multiple)) + self._update_hfss_extent_info(info) + + def get_air_box_negative_vertical_extent(self): + info = self._edb_hfss_extent_info + return info.AirBoxNegativeVerticalExtent.Item1, info.AirBoxNegativeVerticalExtent.Item2 + @property def base_polygon(self): """Base polygon. @@ -143,12 +171,13 @@ def base_polygon(self): ------- :class:`dotnet.database.edb_data.primitives_data.EDBPrimitive` """ - return cast(self._edb_hfss_extent_info.BasePolygon, self._pedb) + return cast(self._edb_hfss_extent_info.BasePolygon, self._pedb).aedt_name @base_polygon.setter def base_polygon(self, value): info = self._edb_hfss_extent_info - info.BasePolygon = value.primitive_object + obj = self._pedb.layout.find_primitive(name=value)[0] + info.BasePolygon = obj._edb_object self._update_hfss_extent_info(info) @property @@ -159,12 +188,13 @@ def dielectric_base_polygon(self): ------- :class:`dotnet.database.edb_data.primitives_data.EDBPrimitive` """ - return cast(self._edb_hfss_extent_info.DielectricBasePolygon, self._pedb) + return cast(self._edb_hfss_extent_info.DielectricBasePolygon, self._pedb).aedt_name @dielectric_base_polygon.setter def dielectric_base_polygon(self, value): info = self._edb_hfss_extent_info - info.DielectricBasePolygon = value.primitive_object + obj = self._pedb.layout.find_primitive(name=value)[0] + info.DielectricBasePolygon = obj.primitive_object self._update_hfss_extent_info(info) @property @@ -189,6 +219,15 @@ def dielectric_extent_size(self, value): info.DielectricExtentSize = convert_pytuple_to_nettuple((value, self.dielectric_extent_size_enabled)) self._update_hfss_extent_info(info) + def set_dielectric_extent(self, size: float, is_multiple: bool = True): + hfss_extent = self._edb_hfss_extent_info + hfss_extent.DielectricExtentSize = convert_pytuple_to_nettuple((size, is_multiple)) + self._update_hfss_extent_info(hfss_extent) + + def get_dielectric_extent(self): + hfss_extent = self._edb_hfss_extent_info + return hfss_extent.DielectricExtentSize.Item1, hfss_extent.DielectricExtentSize.Item2 + @property def dielectric_extent_type(self): """Dielectric extent type.""" @@ -253,7 +292,7 @@ def operating_freq(self): ------- pyedb.dotnet.database.edb_data.edbvalue.EdbValue """ - return EdbValue(self._edb_hfss_extent_info.OperatingFreq) + return Value(self._pedb, self._edb_hfss_extent_info.OperatingFreq) @operating_freq.setter def operating_freq(self, value): @@ -265,7 +304,7 @@ def operating_freq(self, value): @property def radiation_level(self): """PML Radiation level to calculate the thickness of boundary.""" - return EdbValue(self._edb_hfss_extent_info.RadiationLevel) + return Value(self._pedb, self._edb_hfss_extent_info.RadiationLevel) @radiation_level.setter def radiation_level(self, value): @@ -274,6 +313,15 @@ def radiation_level(self, value): info.RadiationLevel = value self._update_hfss_extent_info(info) + @property + def pml_radiation_factor(self): + """PML Radiation level to calculate the thickness of boundary.""" + return self.radiation_level + + @pml_radiation_factor.setter + def pml_radiation_factor(self, value): + self.radiation_level = value + @property def sync_air_box_vertical_extent(self): """Vertical extent of the sync air box.""" diff --git a/tests/system/test_edb_configuration_2p0.py b/tests/system/test_edb_configuration_2p0.py index acd14f9b9d..640bcb6da3 100644 --- a/tests/system/test_edb_configuration_2p0.py +++ b/tests/system/test_edb_configuration_2p0.py @@ -491,33 +491,6 @@ def test_06_s_parameters(self, edb_examples): edbapp.configuration.get_data_from_db(s_parameters=True) edbapp.close(terminate_rpc_session=False) - @pytest.mark.skipif(condition=config["use_grpc"], reason="Not implemented with grpc") - def test_07_boundaries(self, edb_examples): - data = { - "boundaries": { - "open_region": True, - "open_region_type": "radiation", - "pml_visible": False, - "pml_operation_frequency": "5GHz", - "pml_radiation_factor": "10", - "dielectric_extent_type": "bounding_box", - # "dielectric_base_polygon": "", - "horizontal_padding": 0.0, - "honor_primitives_on_dielectric_layers": True, - "air_box_extent_type": "bounding_box", - # "air_box_base_polygon": "", - "air_box_truncate_model_ground_layers": False, - "air_box_horizontal_padding": 0.15, - "air_box_positive_vertical_padding": 1.0, - "air_box_negative_vertical_padding": 1.0, - } - } - edbapp = edb_examples.get_si_verse() - assert edbapp.configuration.load(data, apply_file=True) - data_from_db = edbapp.configuration.get_data_from_db(boundaries=True) - assert data == data_from_db - edbapp.close(terminate_rpc_session=False) - @pytest.mark.skipif(condition=config["use_grpc"], reason="Not implemented with grpc") def test_operations_cutout_auto_identify_nets(self, edb_examples): data = { @@ -1713,3 +1686,107 @@ def test_01a_setups_frequency_sweeps(self, edb_examples): sweep2 = setup["freq_sweep"][1] assert sweep2["type"] == "discrete" edbapp.close(terminate_rpc_session=False) + + +@pytest.mark.skipif(condition=config["use_grpc"], reason="Not implemented with grpc") +class TestClassBoundaries(BaseTestClass): + def test_open_region_radiation(self, edb_examples): + edbapp = edb_examples.get_si_verse() + + data = { + "boundaries": { + "use_open_region": False, + "open_region_type": "radiation", + } + } + edbapp.configuration.load(data, apply_file=True) + assert edbapp.hfss.hfss_extent_info.use_open_region is False + + data = { + "boundaries": { + "use_open_region": True, + "open_region_type": "radiation", + } + } + edbapp.configuration.load(data, apply_file=True) + assert edbapp.hfss.hfss_extent_info.open_region_type == "radiation" + + edbapp.close(terminate_rpc_session=False) + + def test_open_region_pml(self, edb_examples): + edbapp = edb_examples.get_si_verse() + + data = { + "boundaries": { + "use_open_region": True, + "open_region_type": "pml", + "is_pml_visible": True, + "operating_freq": "3GHz", + "pml_radiation_factor": "20", + } + } + edbapp.configuration.load(data, apply_file=True) + assert edbapp.hfss.hfss_extent_info.open_region_type == "pml" + assert edbapp.hfss.hfss_extent_info.is_pml_visible is True + assert edbapp.hfss.hfss_extent_info.operating_freq == 3e9 + assert edbapp.hfss.hfss_extent_info.radiation_level == 20 + + edbapp.close(terminate_rpc_session=False) + + def test_extent_dielectric(self, edb_examples): + edbapp = edb_examples.get_si_verse() + data = { + "boundaries": { + "dielectric_extent_type": "bounding_box", + "dielectric_extent_size": {"size": 0.01, "is_multiple": True}, + "honor_user_dielectric": False, + } + } + edbapp.configuration.load(data, apply_file=True) + assert edbapp.hfss.hfss_extent_info.dielectric_extent_type == "bounding_box" + assert edbapp.hfss.hfss_extent_info.dielectric_extent_size == 0.01 + assert edbapp.hfss.hfss_extent_info.honor_user_dielectric is False + + data = { + "boundaries": { + "dielectric_extent_type": "polygon", + "dielectric_base_polygon": "poly_5949", + "honor_user_dielectric": True, + } + } + edbapp.configuration.load(data, apply_file=True) + assert edbapp.hfss.hfss_extent_info.dielectric_extent_type == "polygon" + assert edbapp.hfss.hfss_extent_info.dielectric_base_polygon == "poly_5949" + assert edbapp.hfss.hfss_extent_info.honor_user_dielectric is True + edbapp.close(terminate_rpc_session=False) + + def test_extent_air(self, edb_examples): + data = { + "boundaries": { + "extent_type": "bounding_box", + "truncate_air_box_at_ground": True, + "air_box_horizontal_extent": {"size": 0.15, "is_multiple": True}, + "air_box_positive_vertical_extent": {"size": 1.0, "is_multiple": True}, + "air_box_negative_vertical_extent": {"size": 2.0, "is_multiple": True}, + "sync_air_box_vertical_extent": True, + } + } + edbapp = edb_examples.get_si_verse() + edbapp.configuration.load(data, apply_file=True) + assert edbapp.hfss.hfss_extent_info.extent_type == "bounding_box" + assert edbapp.hfss.hfss_extent_info.truncate_air_box_at_ground is True + assert edbapp.hfss.hfss_extent_info.air_box_horizontal_extent == 0.15 + assert edbapp.hfss.hfss_extent_info.air_box_positive_vertical_extent == 1.0 + assert edbapp.hfss.hfss_extent_info.air_box_negative_vertical_extent == 2.0 + assert edbapp.hfss.hfss_extent_info.sync_air_box_vertical_extent is True + + data = { + "boundaries": { + "extent_type": "polygon", + "base_polygon": "poly_5949", + } + } + edbapp.configuration.load(data, apply_file=True) + assert edbapp.hfss.hfss_extent_info.extent_type == "polygon" + assert edbapp.hfss.hfss_extent_info.base_polygon == "poly_5949" + edbapp.close(terminate_rpc_session=False)