Skip to content

Commit

Permalink
feat: New API update_semiconductor_wearout_props() (#488)
Browse files Browse the repository at this point in the history
Co-authored-by: pyansys-ci-bot <[email protected]>
  • Loading branch information
ansnfernand and pyansys-ci-bot authored Jan 22, 2025
1 parent 5e997ed commit 3ac7086
Show file tree
Hide file tree
Showing 4 changed files with 230 additions and 3 deletions.
1 change: 1 addition & 0 deletions doc/changelog.d/488.added.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
feat: New API update_semiconductor_wearout_props()
71 changes: 70 additions & 1 deletion src/ansys/sherlock/core/analysis.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Copyright (C) 2023-2024 ANSYS, Inc. and/or its affiliates.
# Copyright (C) 2023-2025 ANSYS, Inc. and/or its affiliates.

"""Module containing all analysis capabilities."""
from typing import Optional
Expand All @@ -14,6 +14,7 @@
UpdatePcbModelingPropsRequestAnalysisType,
UpdatePcbModelingPropsRequestPcbMaterialModel,
UpdatePcbModelingPropsRequestPcbModelType,
UpdateSemiconductorWearoutAnalysisPropsRequest,
)

try:
Expand Down Expand Up @@ -2234,3 +2235,71 @@ def update_component_failure_mechanism_analysis_props(
for return_code in self.stub.updateComponentFailureMechanismProps(update_request):
responses.append(return_code)
return responses

@require_version(252)
def update_semiconductor_wearout_props(
self,
request: UpdateSemiconductorWearoutAnalysisPropsRequest,
) -> list[SherlockCommonService_pb2.ReturnCode]:
r"""Update properties for one or more Semiconductor Wearout Analysis.
Parameters
----------
request: UpdateSemiconductorWearoutAnalysisPropsRequest
Contains all the information needed to update the properties for one or more
semiconductor wearout analyses per project.
Returns
-------
list[SherlockCommonService_pb2.ReturnCode]
Return codes for each request.
Examples
--------
>>> from ansys.sherlock.core.launcher import launch_sherlock
>>> from ansys.sherlock.core.types.analysis_types import (
SemiconductorWearoutAnalysis,
UpdateSemiconductorWearoutAnalysisPropsRequest,
)
>>> sherlock = launch_sherlock()
>>> sherlock.project.import_project_zip_archive(
project="Assembly Tutorial",
category="category",
archive_file=\
"C:\\Program Files\\ANSYS Inc\\v252\\sherlock\\tutorial\\Assembly Tutorial.zip",
)
>>> update_request1 = SemiconductorWearoutAnalysis(
cca_name="Main Board",
max_feature_size=1.5,
max_feature_size_units="mm",
part_temp_rise=10.0,
part_temp_rise_units="C",
part_temp_rise_min_enabled=True,
part_validation_enabled=False,
)
>>> update_request2 = SemiconductorWearoutAnalysis(
cca_name="Memory Card 1",
max_feature_size=2.0,
max_feature_size_units="mm",
part_temp_rise=15.0,
part_temp_rise_units="C",
part_temp_rise_min_enabled=False,
part_validation_enabled=True,
)
>>> request = UpdateSemiconductorWearoutAnalysisPropsRequest(
project="Test",
semiconductor_wearout_analysis_properties=[
update_request1,
update_request2
]
)
>>> return_codes = sherlock.analysis.update_semiconductor_wearout_props(request)
>>> for return_code in return_codes:
print(f"Return code: value={return_code.value}, message={return_code.message}")
"""
update_request = request._convert_to_grpc()

responses = []
for return_code in self.stub.updateSemiconductorWearoutAnalysisProps(update_request):
responses.append(return_code)
return responses
71 changes: 70 additions & 1 deletion src/ansys/sherlock/core/types/analysis_types.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# © 2023-2024 ANSYS, Inc. All rights reserved.
# © 2023-2025 ANSYS, Inc. All rights reserved.

"""Module containing types for the Analysis Service."""

Expand Down Expand Up @@ -179,3 +179,72 @@ def _convert_to_grpc(
for properties in self.component_failure_mechanism_properties_per_cca:
request.componentFailureMechanismProperties.append(properties._convert_to_grpc())
return request


class SemiconductorWearoutAnalysis(BaseModel):
"""Contains the properties of a semiconductor wearout analysis update request."""

cca_name: str
"""Name of the CCA."""
max_feature_size: float
"""Maximum feature size."""
max_feature_size_units: str
"""Units of the maximum feature size."""
part_temp_rise: float
"""Part temperature rise."""
part_temp_rise_units: str
"""Units of the part temperature rise."""
part_temp_rise_min_enabled: bool
"""Whether part temperature rise value is applied to the minimum temperature defined in the
thermal cycle."""
part_validation_enabled: bool
"""Whether part validation should be performed."""

def _convert_to_grpc(
self,
) -> (
analysis_service.UpdateSemiconductorWearoutAnalysisPropsRequest.SemiconductorWearoutAnalysis
):

request_class = analysis_service.UpdateSemiconductorWearoutAnalysisPropsRequest
semiconductor_wearout_analysis = request_class.SemiconductorWearoutAnalysis
grpc_data = semiconductor_wearout_analysis()

grpc_data.ccaName = self.cca_name
grpc_data.maxFeatureSize = self.max_feature_size
grpc_data.maxFeatureSizeUnits = self.max_feature_size_units
grpc_data.partTempRise = self.part_temp_rise
grpc_data.partTempRiseUnits = self.part_temp_rise_units
grpc_data.partTempRiseMinEnabled = self.part_temp_rise_min_enabled
grpc_data.partValidationEnabled = self.part_validation_enabled
return grpc_data

@field_validator("cca_name", "max_feature_size_units", "part_temp_rise_units")
@classmethod
def str_validation(cls, value: str, info: ValidationInfo):
"""Validate string fields listed."""
return basic_str_validator(value, info.field_name)


class UpdateSemiconductorWearoutAnalysisPropsRequest(BaseModel):
"""Contains the properties of a semiconductor wearout analysis update per project."""

project: str
"""Name of the Sherlock project."""
semiconductor_wearout_analysis_properties: list[SemiconductorWearoutAnalysis]
"""List of semiconductor wearout analysis properties to update."""

@field_validator("project")
@classmethod
def str_validation(cls, value: str, info: ValidationInfo):
"""Validate string fields listed."""
return basic_str_validator(value, info.field_name)

def _convert_to_grpc(
self,
) -> analysis_service.UpdateSemiconductorWearoutAnalysisPropsRequest:
request = analysis_service.UpdateSemiconductorWearoutAnalysisPropsRequest()
request.project = self.project
for properties in self.semiconductor_wearout_analysis_properties:
request.semiconductorWearoutAnalysisProperties.append(properties._convert_to_grpc())
return request
90 changes: 89 additions & 1 deletion tests/test_analysis.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Copyright (C) 2023-2024 ANSYS, Inc. and/or its affiliates.
# Copyright (C) 2023-2025 ANSYS, Inc. and/or its affiliates.

try:
import SherlockAnalysisService_pb2
Expand Down Expand Up @@ -32,10 +32,12 @@
ModelSource,
RunAnalysisRequestAnalysisType,
RunStrainMapAnalysisRequestAnalysisType,
SemiconductorWearoutAnalysis,
UpdateComponentFailureMechanismPropsRequest,
UpdatePcbModelingPropsRequestAnalysisType,
UpdatePcbModelingPropsRequestPcbMaterialModel,
UpdatePcbModelingPropsRequestPcbModelType,
UpdateSemiconductorWearoutAnalysisPropsRequest,
)
from ansys.sherlock.core.utils.version_check import SKIP_VERSION_CHECK

Expand Down Expand Up @@ -2026,5 +2028,91 @@ def helper_test_update_component_failure_mechanism_props(analysis: Analysis):
assert return_code.message == ""


def helper_test_update_semiconductor_wearout_props(analysis: Analysis):
"""Test update semiconductor wearout properties API."""
try:
SemiconductorWearoutAnalysis(
cca_name="",
max_feature_size=0.1,
max_feature_size_units="mm",
part_temp_rise=10.0,
part_temp_rise_units="C",
part_temp_rise_min_enabled=True,
part_validation_enabled=False,
)
pytest.fail("No exception raised when using an invalid parameter")
except Exception as e:
assert isinstance(e, pydantic.ValidationError)
assert (
e.errors()[0]["msg"] == "Value error, cca_name is invalid because it is None or empty."
)

try:
UpdateSemiconductorWearoutAnalysisPropsRequest(
project="",
)
pytest.fail("No exception raised when using an invalid parameter")
except Exception as e:
assert isinstance(e, pydantic.ValidationError)
assert (
e.errors()[0]["msg"] == "Value error, project is invalid because it is None or empty."
)

try:
UpdateSemiconductorWearoutAnalysisPropsRequest(
project="Test",
semiconductor_wearout_analysis_properties=["Not a SemiconductorWearoutAnalysis"],
)
pytest.fail("No exception raised when using an invalid parameter")
except Exception as e:
assert isinstance(e, pydantic.ValidationError)
assert (
e.errors()[0]["msg"]
== "Input should be a valid dictionary or instance of SemiconductorWearoutAnalysis"
)

semiconductor_wearout_analysis = SemiconductorWearoutAnalysis(
cca_name="Main Board",
max_feature_size=1.5,
max_feature_size_units="mm",
part_temp_rise=10.0,
part_temp_rise_units="C",
part_temp_rise_min_enabled=True,
part_validation_enabled=False,
)
semiconductor_wearout_analysis2 = SemiconductorWearoutAnalysis(
cca_name="Memory Card 1",
max_feature_size=2.0,
max_feature_size_units="mm",
part_temp_rise=15.0,
part_temp_rise_units="C",
part_temp_rise_min_enabled=False,
part_validation_enabled=True,
)
request = UpdateSemiconductorWearoutAnalysisPropsRequest(
project="Invalid project",
semiconductor_wearout_analysis_properties=[
semiconductor_wearout_analysis,
semiconductor_wearout_analysis2,
],
)

if analysis._is_connection_up():
responses = analysis.update_semiconductor_wearout_props(request)

assert len(responses) == 2
for return_code in responses:
assert return_code.value == -1
assert return_code.message == f"Cannot find project: {request.project}"

request.project = "AssemblyTutorial"
responses = analysis.update_semiconductor_wearout_props(request)

assert len(responses) == 2
for return_code in responses:
assert return_code.value == 0
assert return_code.message == ""


if __name__ == "__main__":
test_all()

0 comments on commit 3ac7086

Please sign in to comment.