From 3ac7086702c5064efb48735586d42800ee287b44 Mon Sep 17 00:00:00 2001 From: Nayane Fernandes <143632290+ansnfernand@users.noreply.github.com> Date: Wed, 22 Jan 2025 17:08:06 +0100 Subject: [PATCH] feat: New API update_semiconductor_wearout_props() (#488) Co-authored-by: pyansys-ci-bot <92810346+pyansys-ci-bot@users.noreply.github.com> --- doc/changelog.d/488.added.md | 1 + src/ansys/sherlock/core/analysis.py | 71 ++++++++++++++- .../sherlock/core/types/analysis_types.py | 71 ++++++++++++++- tests/test_analysis.py | 90 ++++++++++++++++++- 4 files changed, 230 insertions(+), 3 deletions(-) create mode 100644 doc/changelog.d/488.added.md diff --git a/doc/changelog.d/488.added.md b/doc/changelog.d/488.added.md new file mode 100644 index 000000000..bebecdca1 --- /dev/null +++ b/doc/changelog.d/488.added.md @@ -0,0 +1 @@ +feat: New API update_semiconductor_wearout_props() \ No newline at end of file diff --git a/src/ansys/sherlock/core/analysis.py b/src/ansys/sherlock/core/analysis.py index fd57dff74..9ddded02a 100644 --- a/src/ansys/sherlock/core/analysis.py +++ b/src/ansys/sherlock/core/analysis.py @@ -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 @@ -14,6 +14,7 @@ UpdatePcbModelingPropsRequestAnalysisType, UpdatePcbModelingPropsRequestPcbMaterialModel, UpdatePcbModelingPropsRequestPcbModelType, + UpdateSemiconductorWearoutAnalysisPropsRequest, ) try: @@ -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 diff --git a/src/ansys/sherlock/core/types/analysis_types.py b/src/ansys/sherlock/core/types/analysis_types.py index d3f9eb06b..4d1dd26c9 100644 --- a/src/ansys/sherlock/core/types/analysis_types.py +++ b/src/ansys/sherlock/core/types/analysis_types.py @@ -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.""" @@ -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 diff --git a/tests/test_analysis.py b/tests/test_analysis.py index a4c572dbc..1dab86763 100644 --- a/tests/test_analysis.py +++ b/tests/test_analysis.py @@ -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 @@ -32,10 +32,12 @@ ModelSource, RunAnalysisRequestAnalysisType, RunStrainMapAnalysisRequestAnalysisType, + SemiconductorWearoutAnalysis, UpdateComponentFailureMechanismPropsRequest, UpdatePcbModelingPropsRequestAnalysisType, UpdatePcbModelingPropsRequestPcbMaterialModel, UpdatePcbModelingPropsRequestPcbModelType, + UpdateSemiconductorWearoutAnalysisPropsRequest, ) from ansys.sherlock.core.utils.version_check import SKIP_VERSION_CHECK @@ -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()