Note
Go to the end to download the full example code.
Proxy solver#
This example demonstrates how to obtain designs from parametric system and process them externally.
It creates a proxy solver node inside parametric system and solves it’s designs externally.
This is a unified approach for “optiSLang inside” solutions.
Perform required imports#
Perform the required imports.
import time
from ansys.optislang.core import Optislang
import ansys.optislang.core.node_types as node_types
from ansys.optislang.core.nodes import DesignFlow, ParametricSystem, ProxySolverNode
from ansys.optislang.core.project_parametric import (
ComparisonType,
ObjectiveCriterion,
OptimizationParameter,
)
from ansys.optislang.core.utils import find_all_osl_exec
Create solver#
Define a simple calculator function to solve the variations
def calculator(hid, X1, X2, X3, X4, X5):
from math import sin
Y = 0.5 * X1 + X2 + 0.5 * X1 * X2 + 5 * sin(X3) + 0.2 * X4 + 0.1 * X5
return Y
def calculate(designs):
result_design_list = []
print(f"Calculate {len(designs)} designs")
for design in designs:
hid = design["hid"]
parameters = design["parameters"]
X1 = 0.0
X2 = 0.0
X3 = 0.0
X4 = 0.0
X5 = 0.0
for parameter in parameters:
if parameter["name"] == "X1":
X1 = parameter["value"]
elif parameter["name"] == "X2":
X2 = parameter["value"]
elif parameter["name"] == "X3":
X3 = parameter["value"]
elif parameter["name"] == "X4":
X4 = parameter["value"]
elif parameter["name"] == "X5":
X5 = parameter["value"]
Y = calculator(hid, X1, X2, X3, X4, X5)
result_design = {}
result_design["hid"] = hid
responses = [{"name": "Y", "value": Y}]
result_design["responses"] = responses
result_design_list.append(result_design)
print(f"Return {len(result_design_list)} designs")
return result_design_list
Create optiSLang instance#
Find the optiSLang >= 25.1 executable. Initialize the Optislang class instance with the executable.
available_optislang_executables = find_all_osl_exec()
version, executables = available_optislang_executables.popitem(last=False)
if not version >= 251:
raise KeyError("OptiSLang installation >= 25R1 wasn't found, please specify path manually.")
osl = Optislang(executable=executables[0])
print(f"Using optiSLang version {osl.osl_version_string}")
Create workflow#
root_system = osl.application.project.root_system
# Create the algorithm system of your choice.
algorithm_system: ParametricSystem = root_system.create_node(
type_=node_types.Sensitivity, name="Sensitivity"
)
num_discretization = 2000
algorithm_settings = algorithm_system.get_property("AlgorithmSettings")
algorithm_settings["num_discretization"] = num_discretization
algorithm_system.set_property("AlgorithmSettings", algorithm_settings)
# Fast running solver settings
algorithm_system.set_property("AutoSaveMode", "no_auto_save")
algorithm_system.set_property("SolveTwice", True)
algorithm_system.set_property("UpdateResultFile", "never")
algorithm_system.set_property("WriteDesignStartSetFlag", False)
# Add the Proxy Solver node and set the desired maximum number of designs you handle in one go.
proxy_solver: ProxySolverNode = algorithm_system.create_node(
type_=node_types.ProxySolver, name="Calculator", design_flow=DesignFlow.RECEIVE_SEND
)
multi_design_launch_num = 99 # set -1 to solve all designs simultaneously
proxy_solver.set_property("MultiDesignLaunchNum", multi_design_launch_num)
proxy_solver.set_property("ForwardHPCLicenseContextEnvironment", True)
# Load the available parameters and responses.
load_json = {}
load_json["parameters"] = []
load_json["responses"] = []
for i in range(1, 6):
parameter = {"dir": {"value": "input"}, "name": f"X{i}", "value": 1.0}
load_json["parameters"].append(parameter)
response = {"dir": {"value": "output"}, "name": "Y", "value": 3.0}
load_json["responses"].append(response)
proxy_solver.load(args=load_json)
# Register parameters and responses to be available in the algorithm system
proxy_solver.register_locations_as_parameter()
proxy_solver.register_locations_as_response()
# Change parameter bounds.
for i in range(1, 6):
algorithm_system.parameter_manager.modify_parameter(
OptimizationParameter(name=f"X{i}", reference_value=1.0, range=(-3.14, 3.14))
)
# Create a criterion in the algorithm system
algorithm_system.criteria_manager.add_criterion(
ObjectiveCriterion(name="obj", expression="Y", criterion=ComparisonType.MIN)
)
Optionally save project#
If you want to save the project to some desired location, uncomment and edit these lines:
dir_path = Path(r"<insert-desired-location>")
project_name = "proxy_solver_workflow.opf"
osl.application.save_as(dir_path / project_name)
Run workflow#
Run the workflow created by the preceding scripts.
# Start the optiSLang project execution.
osl.application.project.start(wait_for_finished=False)
# Now loop until get_status() returns "Processing done" for the root system. Use the GET_DESIGNS query and the SET_DESIGNS command for the Proxy Solver node to get designs and set responses until the system is done.
while not osl.project.root_system.get_status() == "Processing done":
design_list = proxy_solver.get_designs()
if len(design_list):
responses_dict = calculate(design_list)
proxy_solver.set_designs(responses_dict)
# time.sleep(0.1)
print("Solved Successfully!")
Stop and cancel project#
Stop and cancel the project.
osl.dispose()
View generated workflow#
This image shows the generated workflow. However, it is important to note, that this workflow is only usable through pyoptislang and cannot be used interactively!