From 7671f7cca72a91bd24073a4e953bfd19dc1632f5 Mon Sep 17 00:00:00 2001 From: ojkoenig Date: Fri, 12 Aug 2022 08:16:33 +0200 Subject: [PATCH 1/2] Initial exploration and examples for execution scripts --- .../exec_mapdl.py | 14 +++++- examples/exec_scripts/exec_python.py | 46 +++++++++++++++++++ .../mapdl_motorbike_frame/project_setup.py | 20 ++++---- 3 files changed, 68 insertions(+), 12 deletions(-) rename examples/{mapdl_motorbike_frame => exec_scripts}/exec_mapdl.py (84%) create mode 100644 examples/exec_scripts/exec_python.py diff --git a/examples/mapdl_motorbike_frame/exec_mapdl.py b/examples/exec_scripts/exec_mapdl.py similarity index 84% rename from examples/mapdl_motorbike_frame/exec_mapdl.py rename to examples/exec_scripts/exec_mapdl.py index 821c41423..1ccf9a62d 100644 --- a/examples/mapdl_motorbike_frame/exec_mapdl.py +++ b/examples/exec_scripts/exec_mapdl.py @@ -1,3 +1,10 @@ +""" +Basic execution script for MAPDL. + +Command formed: ansys.exe -b -i -o -np 4 + +""" + import json import subprocess @@ -14,8 +21,8 @@ def execute(self): f.write(context_d) # Identify files - inp_file = next((f for f in self.context.input_files if f["name"] == "mac"), None) - assert inp_file, "Input file mac missing" + inp_file = next((f for f in self.context.input_files if f["name"] == "inp"), None) + assert inp_file, "Input file inp missing" out_file = next((f for f in self.context.output_files if f["name"] == "out"), None) assert out_file, "Output file out missing" @@ -32,6 +39,9 @@ def execute(self): # Use properties from resource requirements num_cores = self.context.resource_requirements["num_cores"] + # Form command cmd = f"{exe} -b -i {inp_file['path']} -o {out_file['path']} -np {num_cores}" + + # Execute command log.info(f"Executing: {cmd}") subprocess.run(cmd, shell=True, check=True) diff --git a/examples/exec_scripts/exec_python.py b/examples/exec_scripts/exec_python.py new file mode 100644 index 000000000..a442af9dd --- /dev/null +++ b/examples/exec_scripts/exec_python.py @@ -0,0 +1,46 @@ +""" +Simplistic execution script for Python. + +Command formed: python +""" + +import json +import subprocess + +from ansys.rep.common.logging import log +from ansys.rep.evaluator.task_manager import ApplicationExecution + + +class PythonExecution(ApplicationExecution): + def execute(self): + + # Dump whole context to file for debugging + context_d = json.dumps(vars(self.context), indent=4, default=str) + with open("context.txt", "w") as f: + f.write(context_d) + + # Identify files + script_file = next((f for f in self.context.input_files if f["name"] == "script"), None) + assert inp_file, "Python script file script missing" + inp_file = next((f for f in self.context.input_files if f["name"] == "inp"), None) + assert inp_file, "Input file inp missing" + + # Identify application + app_name = "Python" + app = next((a for a in self.context.applications if a["name"] == app_name), None) + assert app, f"Cannot find app {app_name}" + + # Add " around exe if needed for Windows + exe = app["executable"] + if " " in exe and not exe.startswith('"'): + exe = '"%s"' % exe + + # Use properties from resource requirements + # None currently + + # Form command + cmd = f"{exe} {script_file['path']} {inp_file['path']}" + + # Execute + log.info(f"Executing: {cmd}") + subprocess.run(cmd, shell=True, check=True) diff --git a/examples/mapdl_motorbike_frame/project_setup.py b/examples/mapdl_motorbike_frame/project_setup.py index c2c189f8a..dba95ae29 100644 --- a/examples/mapdl_motorbike_frame/project_setup.py +++ b/examples/mapdl_motorbike_frame/project_setup.py @@ -52,7 +52,7 @@ def create_project(client, name, num_jobs=20, use_exec_script=False): files = [] files.append( File( - name="mac", + name="inp", evaluation_path="motorbike_frame.mac", type="text/plain", src=os.path.join(cwd, "motorbike_frame.mac"), @@ -84,7 +84,7 @@ def create_project(client, name, num_jobs=20, use_exec_script=False): name="exec_mapdl", evaluation_path="exec_mapdl.py", type="application/x-python-code", - src=os.path.join(cwd, "exec_mapdl.py"), + src=os.path.join(cwd, "..", "exec_scripts", "exec_mapdl.py"), ) ) @@ -117,7 +117,7 @@ def create_project(client, name, num_jobs=20, use_exec_script=False): key_string="radius(%i)" % i, tokenizer="=", parameter_definition_id=float_input_params[pi].id, - file_id=file_ids["mac"], + file_id=file_ids["inp"], ) ) pi += 1 @@ -126,7 +126,7 @@ def create_project(client, name, num_jobs=20, use_exec_script=False): key_string="thickness(%i)" % i, tokenizer="=", parameter_definition_id=float_input_params[pi].id, - file_id=file_ids["mac"], + file_id=file_ids["inp"], ) ) pi += 1 @@ -145,7 +145,7 @@ def create_project(client, name, num_jobs=20, use_exec_script=False): key_string="tubes(%i)" % i, tokenizer="=", parameter_definition_id=str_input_params[i - 1].id, - file_id=file_ids["mac"], + file_id=file_ids["inp"], ) ) @@ -204,7 +204,7 @@ def create_project(client, name, num_jobs=20, use_exec_script=False): tokenizer="=", string_quote="'", task_definition_property="name", - file_id=file_ids["mac"], + file_id=file_ids["inp"], ) ) param_mappings.append( @@ -213,7 +213,7 @@ def create_project(client, name, num_jobs=20, use_exec_script=False): tokenizer="=", string_quote="'", task_definition_property="software_requirements[0].name", - file_id=file_ids["mac"], + file_id=file_ids["inp"], ) ) param_mappings.append( @@ -221,7 +221,7 @@ def create_project(client, name, num_jobs=20, use_exec_script=False): key_string="num_cores", tokenizer="=", task_definition_property="num_cores", - file_id=file_ids["mac"], + file_id=file_ids["inp"], ) ) param_mappings.append( @@ -229,7 +229,7 @@ def create_project(client, name, num_jobs=20, use_exec_script=False): key_string="cpu_core_usage", tokenizer="=", task_definition_property="resource_requirements.cpu_core_usage", - file_id=file_ids["mac"], + file_id=file_ids["inp"], ) ) @@ -239,7 +239,7 @@ def create_project(client, name, num_jobs=20, use_exec_script=False): software_requirements=[ Software(name="ANSYS Mechanical APDL", version=ansys_version), ], - execution_command="%executable% -b -i %file:mac% -o file.out -np %resource:num_cores%", + execution_command="%executable% -b -i %file:inp% -o file.out -np %resource:num_cores%", resource_requirements=ResourceRequirements( cpu_core_usage=1.0, memory=250, From da0d4bfdcff621e95c3362df2b06e793b98ca6f0 Mon Sep 17 00:00:00 2001 From: ojkoenig Date: Fri, 12 Aug 2022 22:23:52 +0200 Subject: [PATCH 2/2] Getting example with python exec script to run --- examples/exec_scripts/exec_python.py | 2 +- .../project_setup.py | 63 +++++++++++-------- 2 files changed, 39 insertions(+), 26 deletions(-) diff --git a/examples/exec_scripts/exec_python.py b/examples/exec_scripts/exec_python.py index a442af9dd..8a67495d7 100644 --- a/examples/exec_scripts/exec_python.py +++ b/examples/exec_scripts/exec_python.py @@ -21,7 +21,7 @@ def execute(self): # Identify files script_file = next((f for f in self.context.input_files if f["name"] == "script"), None) - assert inp_file, "Python script file script missing" + assert script_file, "Python script file script missing" inp_file = next((f for f in self.context.input_files if f["name"] == "inp"), None) assert inp_file, "Input file inp missing" diff --git a/examples/python_two_bar_truss_problem/project_setup.py b/examples/python_two_bar_truss_problem/project_setup.py index e0f41059f..98aa84fc8 100644 --- a/examples/python_two_bar_truss_problem/project_setup.py +++ b/examples/python_two_bar_truss_problem/project_setup.py @@ -26,7 +26,7 @@ log = logging.getLogger(__name__) -def main(client, num_jobs): +def main(client, num_jobs, use_exec_script): """ Create project solving a Two-Bar Truss problem with Python. @@ -45,7 +45,7 @@ def main(client, num_jobs): files = [] files.append( File( - name="input_params", + name="inp", evaluation_path="input_parameters.json", type="text/plain", src=os.path.join(cwd, "input_parameters.json"), @@ -53,7 +53,7 @@ def main(client, num_jobs): ) files.append( File( - name="pyscript", + name="script", evaluation_path="evaluate.py", type="text/plain", src=os.path.join(cwd, "evaluate.py"), @@ -61,21 +61,30 @@ def main(client, num_jobs): ) files.append( File( - name="results", + name="result", evaluation_path="output_parameters.json", type="text/plain", collect=True, ) ) - files = proj.create_files(files) + if use_exec_script: + # Define and upload an exemplary exec script to run MAPDL + files.append( + File( + name="exec_python", + evaluation_path="exec_python.py", + type="application/x-python-code", + src=os.path.join(cwd, "..", "exec_scripts", "exec_python.py"), + ) + ) - input_file = files[0] - result_file = files[2] + files = proj.create_files(files) + file_ids = {f.name: f.id for f in files} log.debug("=== JobDefinition with simulation workflow and parameters") job_def = JobDefinition( - name="job_definition.1", + name="JobDefinition.1", active=True, ) @@ -110,43 +119,43 @@ def main(client, num_jobs): key_string='"H"', tokenizer=":", parameter_definition_id=input_params[0].id, - file_id=input_file.id, + file_id=file_ids["inp"], ), ParameterMapping( key_string='"d"', tokenizer=":", parameter_definition_id=input_params[1].id, - file_id=input_file.id, + file_id=file_ids["inp"], ), ParameterMapping( key_string='"t"', tokenizer=":", parameter_definition_id=input_params[2].id, - file_id=input_file.id, + file_id=file_ids["inp"], ), ParameterMapping( key_string='"B"', tokenizer=":", parameter_definition_id=input_params[3].id, - file_id=input_file.id, + file_id=file_ids["inp"], ), ParameterMapping( key_string='"E"', tokenizer=":", parameter_definition_id=input_params[4].id, - file_id=input_file.id, + file_id=file_ids["inp"], ), ParameterMapping( key_string='"rho"', tokenizer=":", parameter_definition_id=input_params[5].id, - file_id=input_file.id, + file_id=file_ids["inp"], ), ParameterMapping( key_string='"P"', tokenizer=":", parameter_definition_id=input_params[6].id, - file_id=input_file.id, + file_id=file_ids["inp"], ), ] @@ -164,25 +173,25 @@ def main(client, num_jobs): key_string='"weight"', tokenizer=":", parameter_definition_id=output_params[0].id, - file_id=result_file.id, + file_id=file_ids["result"], ), ParameterMapping( key_string='"stress"', tokenizer=":", parameter_definition_id=output_params[1].id, - file_id=result_file.id, + file_id=file_ids["result"], ), ParameterMapping( key_string='"buckling_stress"', tokenizer=":", parameter_definition_id=output_params[2].id, - file_id=result_file.id, + file_id=file_ids["result"], ), ParameterMapping( key_string='"deflection"', tokenizer=":", parameter_definition_id=output_params[3].id, - file_id=result_file.id, + file_id=file_ids["result"], ), ] ) @@ -192,11 +201,10 @@ def main(client, num_jobs): job_def.parameter_definition_ids = [o.id for o in input_params + output_params] job_def.parameter_mapping_ids = [o.id for o in mappings] - # Process step task_def = TaskDefinition( name="python_evaluation", software_requirements=[Software(name="Python", version="3.10")], - execution_command="%executable% %file:pyscript% %file:input_params%", + execution_command="%executable% %file:script% %file:inp%", resource_requirements=ResourceRequirements( cpu_core_usage=0.5, memory=100, @@ -204,9 +212,14 @@ def main(client, num_jobs): ), execution_level=0, max_execution_time=30.0, - input_file_ids=[f.id for f in files[:2]], - output_file_ids=[f.id for f in files[2:]], + input_file_ids=[file_ids["script"], file_ids["inp"]], + output_file_ids=[file_ids["result"]], ) + + if use_exec_script: + task_def.execution_command = None + task_def.execution_script_id = file_ids["exec_python"] + task_def = proj.create_task_definitions([task_def])[0] job_def.task_definition_ids = [task_def.id] @@ -257,16 +270,16 @@ def main(client, num_jobs): parser.add_argument("-u", "--username", default="repadmin") parser.add_argument("-p", "--password", default="repadmin") parser.add_argument("-n", "--num-jobs", type=int, default=1000) + parser.add_argument("-es", "--use-exec-script", default=False, action="store_true") args = parser.parse_args() logger = logging.getLogger() logging.basicConfig(format="[%(asctime)s | %(levelname)s] %(message)s", level=logging.DEBUG) - log.debug("=== DCS connection") client = Client(rep_url=args.url, username=args.username, password=args.password) try: - main(client, num_jobs=args.num_jobs) + main(client, num_jobs=args.num_jobs, use_exec_script=args.use_exec_script) except REPError as e: log.error(str(e))