From f23da00bf97220bbf6f4872d0fc2435a54e087c5 Mon Sep 17 00:00:00 2001 From: German <28149841+germa89@users.noreply.github.com> Date: Wed, 22 May 2024 12:33:57 +0200 Subject: [PATCH] Adding APDL jobs support (#3111) * Adding inputs and outputs * Supporting pure APDL jobs * Changing arguments order * Allowing force mode * Apply suggestions from code review Co-authored-by: Kathy Pippert <84872299+PipKat@users.noreply.github.com> --------- Co-authored-by: Kathy Pippert <84872299+PipKat@users.noreply.github.com> --- src/ansys/mapdl/core/cli/hpc.py | 13 ++++++ src/ansys/mapdl/core/hpc/pyhps.py | 72 ++++++++++++++++++++++++++----- 2 files changed, 75 insertions(+), 10 deletions(-) diff --git a/src/ansys/mapdl/core/cli/hpc.py b/src/ansys/mapdl/core/cli/hpc.py index 92f694e51f..1a96aefa3a 100644 --- a/src/ansys/mapdl/core/cli/hpc.py +++ b/src/ansys/mapdl/core/cli/hpc.py @@ -183,6 +183,17 @@ flag_value=True, help="""Whether the terminal is to wait for job completion before returning control to the user. """, ) +@click.option( + "--mode", + default=None, + type=str, + help=""" +Force the job submission to behave as if the main file was a Python, +shell, or APDL file, regardless of its extension type. Allowed values are +``"python"``, ``"shell"``, and ``"apdl"``. +By default, PyMAPDL detects the type of file from its extension. +""", +) @click.option( "--debug", default=False, @@ -213,6 +224,7 @@ def submit( max_execution_time: int = None, wait: bool = False, debug: bool = False, + mode: Optional[Union["python", "shell", "apdl"]] = None, ): import json @@ -268,6 +280,7 @@ def submit( disk_space=disk_space, exclusive=exclusive, max_execution_time=max_execution_time, + mode=mode, ) if save_config_file: diff --git a/src/ansys/mapdl/core/hpc/pyhps.py b/src/ansys/mapdl/core/hpc/pyhps.py index 78f952d301..7ad3e06a04 100644 --- a/src/ansys/mapdl/core/hpc/pyhps.py +++ b/src/ansys/mapdl/core/hpc/pyhps.py @@ -215,6 +215,7 @@ def is_float(num): def create_task( project_api, + mode, main_file, file_input_ids, file_output_ids, @@ -225,13 +226,19 @@ def create_task( max_execution_time, ): - software = Software(name="Bash", version="0.1") # Overwriting + if mode == "apdl": + software = Software(name="Ansys Mechanical APDL", version="2024 R2") + name = "MAPDL Task" + else: + software = Software(name="Bash", version="0.1") # Overwriting + name = "PyMAPDL Task" + execution_command = f"%executable% %file:{os.path.basename(main_file)}%" logger.debug(f"Using executable: '{execution_command}'") # Process step task_def = TaskDefinition( - name="PyMAPDL_task", + name=name, software_requirements=[software], execution_command=execution_command, resource_requirements=ResourceRequirements( @@ -338,15 +345,40 @@ def create_pymapdl_pyhps_job( disk_space: int = None, exclusive: bool = None, max_execution_time: int = None, + mode: Optional[Union["python", "shell", "apdl"]] = None, ): + """ + Workflow + + APDL mode: main_file + + Others: shell_file + + Wrapper + + main_file + """ if python not in [2, 2.7, 3, 3.5, 3.6, 3.7, 3.8, 3.9, 3.10, 3.11, 3.12]: warn(f"Version of Python {python} might not be supported by the cluster.") if not os.path.exists(main_file): - raise ValueError(f"The Python file {main_file} must exist.") + raise ValueError(f"The file {main_file} must exist.") + + logger.debug(f"Main file is in: {main_file}.") + + _, file_extension = os.path.splitext(main_file) + + if mode is None: + if file_extension.lower() in [".sh"]: + mode = "shell" + elif file_extension.lower() in [".py"]: + mode = "python" + elif file_extension.lower() in [".inp", ".mac"]: + mode = "apdl" + else: + if mode.lower() not in ["python", "shell", "apdl"]: + raise Exception("File type is not supported.") - logger.debug(f"Main Python file is in: {main_file}.") + logger.debug( + f"Submission mode set to '{mode}' because of main file ({main_file}) extension." + ) if inputs is None: inputs = [] @@ -355,11 +387,14 @@ def create_pymapdl_pyhps_job( input_file = None if inputs: + if mode == "apdl": + raise ValueError("Inputs are not supported when using APDL files.") + if isinstance(inputs, str): inputs = inputs.split(",") if inputs: - input_file = "input.inp" + input_file = "input.inputs" content = "\n".join(inputs) input_file = _create_tmp_file(input_file, content) @@ -367,7 +402,9 @@ def create_pymapdl_pyhps_job( output_parms_file = None if outputs: - output_parms_file = "output.out" + if mode == "apdl": + raise ValueError("Outputs are not supported when using APDL files.") + output_parms_file = "output.output" if isinstance(outputs, str): outputs = outputs.split(",") @@ -391,6 +428,7 @@ def create_pymapdl_pyhps_job( if outputs: content += f""" +# Write output data with open("{output_parms_file}", "w") as fid: """ b0 = "{" @@ -402,7 +440,7 @@ def create_pymapdl_pyhps_job( wrapper_file = _create_tmp_file(wrapper_file, content) logger.debug(f"Wrapper file in: {wrapper_file}") - if not requirements_file: + if not requirements_file and mode == "python": import pkg_resources content = "\n".join( @@ -411,7 +449,7 @@ def create_pymapdl_pyhps_job( requirements_file = _create_tmp_file("requirements.txt", content) logger.debug(f"Requirements file in: {requirements_file}") - if not shell_file: + if not shell_file and mode == "python": content = f""" echo "Starting" @@ -429,6 +467,14 @@ def create_pymapdl_pyhps_job( shell_file = _create_tmp_file("main.sh", content) logger.debug(f"Shell file in: {shell_file}") + elif shell_file and mode == "shell": + raise ValueError( + "You cannot use a shell file and specify a shell file as a main file. Avoid specifying the '--shell_file' argument." + ) + + elif not shell_file and mode == "shell": + shell_file = main_file + if isinstance(extra_files, str): extra_files = extra_files.split(",") elif extra_files is None: @@ -443,8 +489,13 @@ def create_pymapdl_pyhps_job( raise ValueError("One or more extra files do not exist.") input_files = extra_files - input_files.append(requirements_file) - input_files.append(shell_file) + if mode == "python": + input_files.append(requirements_file) + input_files.append(shell_file) + else: + # we are going to refer to this from now on + shell_file = main_file + input_files.append(main_file) if inputs: @@ -488,6 +539,7 @@ def create_pymapdl_pyhps_job( # Set tasks task_def = create_task( project_api, + mode, shell_file, file_input_ids, file_output_ids,