diff --git a/doc/source/examples/ex_lsdyna_job.rst b/doc/source/examples/ex_lsdyna_job.rst index 137ebfcf..baca736f 100644 --- a/doc/source/examples/ex_lsdyna_job.rst +++ b/doc/source/examples/ex_lsdyna_job.rst @@ -19,6 +19,9 @@ Usage: python lsdyna_job.py monitor python lsdyna_job.py download +.. note:: + This example only runs on Windows platform as the LS-PrePost task requires to open the LS-PREPOST GUI. + .. note:: The ``download`` action requires ``tqdm`` and ``humanize`` packages to show a progress bar during the result files download. You can install them with ``python -m pip install tqdm humanize``. diff --git a/examples/fluent_2d_heat_exchanger/project_setup.py b/examples/fluent_2d_heat_exchanger/project_setup.py index 1e8d9f43..06d9b8a6 100644 --- a/examples/fluent_2d_heat_exchanger/project_setup.py +++ b/examples/fluent_2d_heat_exchanger/project_setup.py @@ -22,8 +22,9 @@ log = logging.getLogger(__name__) -def main(client: Client, name: str, version: str) -> Project: - +def create_project( + client, name, version=__ansys_apps_version__, use_exec_script=False, active=True +) -> Project: log.info("=== Create Project") jms_api = JmsApi(client) proj = Project(name=name, priority=1, active=True) @@ -36,13 +37,13 @@ def main(client: Client, name: str, version: str) -> Project: files = [ File( - name="cas_h5", + name="case", evaluation_path="heat_exchanger.cas.h5", type="application/octet-stream", src=os.path.join(cwd, "heat_exchanger.cas.h5"), ), File( - name="journal", + name="jou", evaluation_path="heat_exchanger.jou", type="text/plain", src=os.path.join(cwd, "heat_exchanger.jou"), @@ -72,22 +73,37 @@ def main(client: Client, name: str, version: str) -> Project: log.debug("=== Job Definition with simulation workflow") # Task Definition + task_defs = [] task_def = TaskDefinition( name="Fluent Run", software_requirements=[Software(name="Ansys Fluent", version=version)], - execution_command="%executable% 2d -g -tm %resource:num_cores% -i %file:journal%", + execution_command="%executable% 2d -g -tm %resource:num_cores% -i %file:jou%", resource_requirements=ResourceRequirements( num_cores=4, memory=4000, disk_space=500, + distributed=True, ), + execution_context={ + "dimension": "2d", + }, max_execution_time=600.0, execution_level=0, num_trials=1, - input_file_ids=[file_ids["cas_h5"], file_ids["journal"]], + input_file_ids=[file_ids["case"], file_ids["jou"]], output_file_ids=[file_ids["trn"], file_ids["output_cas"], file_ids["output_data"]], ) - task_def = project_api.create_task_definitions([task_def])[0] + + if use_exec_script: + task_def.use_execution_script = True + exec_script_file = project_api.copy_default_execution_script( + f"fluent-v{version[2:4]}{version[6]}-exec_fluent.py" + ) + task_def.execution_script_id = exec_script_file.id + + task_defs.append(task_def) + + task_def = project_api.create_task_definitions(task_defs)[0] # Create job_definition in project job_def = JobDefinition(name="JobDefinition.1", active=True) @@ -111,6 +127,7 @@ def main(client: Client, name: str, version: str) -> Project: if __name__ == "__main__": parser = argparse.ArgumentParser() parser.add_argument("-n", "--name", type=str, default="Fluent 2D Heat Exchanger") + parser.add_argument("-es", "--use-exec-script", default=False, type=bool) parser.add_argument("-U", "--url", default="https://localhost:8443/rep") parser.add_argument("-u", "--username", default="repadmin") parser.add_argument("-p", "--password", default="repadmin") @@ -125,6 +142,12 @@ def main(client: Client, name: str, version: str) -> Project: client = Client(rep_url=args.url, username=args.username, password=args.password) try: - main(client, name=args.name, version=args.ansys_version) + log.info(f"REP URL: {client.rep_url}") + proj = create_project( + client=client, + name=args.name, + version=args.ansys_version, + use_exec_script=args.use_exec_script, + ) except REPError as e: log.error(str(e)) diff --git a/examples/lsdyna_cylinder_plate/lsdyna_job.py b/examples/lsdyna_cylinder_plate/lsdyna_job.py index b0295609..9735801f 100644 --- a/examples/lsdyna_cylinder_plate/lsdyna_job.py +++ b/examples/lsdyna_cylinder_plate/lsdyna_job.py @@ -43,7 +43,7 @@ USERNAME = "repadmin" PASSWORD = "repadmin" USE_LSDYNA_MPP = False -ANSYS_VERSION = "2023 R1" +ANSYS_VERSION = "2024 R1" class REPJob: @@ -86,7 +86,7 @@ def load(cls): return job -def submit_job() -> REPJob: +def submit_job(use_exec_script=False) -> REPJob: """Create a REP project running a simple LS-DYNA job simulating the impact of a cylinder made of Aluminum against a plate made of steel. @@ -109,7 +109,7 @@ def submit_job() -> REPJob: # input files files.append( File( - name="input_deck", + name="inp", evaluation_path="cylinder_plate.k", type="text/plain", src=os.path.join(cwd, "cylinder_plate.k"), @@ -177,12 +177,11 @@ def submit_job() -> REPJob: job_def = JobDefinition(name="JobDefinition.1", active=True) # Define process steps (task definitions) - ls_dyna_command = "%executable% i=%file:input_deck% ncpu=%resource:num_cores% memory=300m" + ls_dyna_command = "%executable% i=%file:inp% ncpu=%resource:num_cores% memory=300m" if USE_LSDYNA_MPP: - ls_dyna_command = ( - "%executable% -dis -np %resource:num_cores% i=%file:input_deck% memory=300m" - ) + ls_dyna_command = "%executable% -dis -np %resource:num_cores% i=%file:inp% memory=300m" + task_defs = [] task_def1 = TaskDefinition( name="LS-DYNA Run", software_requirements=[Software(name="Ansys LS-DYNA", version=ANSYS_VERSION)], @@ -192,10 +191,11 @@ def submit_job() -> REPJob: num_cores=6, memory=6000 * 1024 * 1024, disk_space=4000 * 1024 * 1024, + distributed=USE_LSDYNA_MPP, ), execution_level=0, num_trials=1, - input_file_ids=[file_ids["input_deck"]], + input_file_ids=[file_ids["inp"]], output_file_ids=[file_ids["d3hsp"], file_ids["messag"], file_ids["d3plot"]], success_criteria=SuccessCriteria( return_code=0, @@ -205,6 +205,16 @@ def submit_job() -> REPJob: ), ) + if use_exec_script: + exec_script_file = project_api.copy_default_execution_script( + f"lsdyna-v{ANSYS_VERSION[2:4]}{ANSYS_VERSION[6]}-exec_lsdyna.py" + ) + + task_def1.use_execution_script = True + task_def1.execution_script_id = exec_script_file.id + + task_defs.append(task_def1) + task_def2 = TaskDefinition( name="LS-PrePost Run", software_requirements=[Software(name="Ansys LS-PrePost", version=ANSYS_VERSION)], @@ -214,6 +224,8 @@ def submit_job() -> REPJob: num_cores=2, memory=3000, disk_space=4000, + distributed=False, + platform="Windows", ), execution_level=1, num_trials=1, @@ -226,7 +238,9 @@ def submit_job() -> REPJob: ), ) - task_definitions = project_api.create_task_definitions([task_def1, task_def2]) + task_defs.append(task_def2) + + task_definitions = project_api.create_task_definitions(task_defs) # Create job definition in project job_def = JobDefinition(name="JobDefinition.1", active=True) @@ -373,11 +387,17 @@ def download_results(app_job: REPJob): parser.add_argument( "action", default="submit", choices=["submit", "monitor", "download"], help="Action to run" ) + parser.add_argument( + "--exec_script", + default=False, + type=bool, + help="Use default execution script while submitting job", + ) args = parser.parse_args() try: if args.action == "submit": - job = submit_job() + job = submit_job(args.exec_script) job.save() elif args.action == "monitor": job = REPJob.load() diff --git a/examples/mapdl_linked_analyses/project_setup.py b/examples/mapdl_linked_analyses/project_setup.py index eeee0f4b..58281b3d 100644 --- a/examples/mapdl_linked_analyses/project_setup.py +++ b/examples/mapdl_linked_analyses/project_setup.py @@ -43,14 +43,14 @@ def create_prestress_task_definition( - project_api: ProjectApi, version: str + project_api: ProjectApi, use_exec_script: bool, version: str ) -> Tuple[str, List[File]]: log.info("=== Files") cwd = os.path.dirname(__file__) files = [ File( - name="input_deck", + name="inp", evaluation_path="prestres.dat", type="text/plain", src=os.path.join(cwd, "prestress.dat"), @@ -90,27 +90,40 @@ def create_prestress_task_definition( files = project_api.create_files(files) file_ids = {f.name: f.id for f in files} + task_defs = [] task_def = TaskDefinition( name="Prestress", software_requirements=[Software(name="Ansys Mechanical APDL", version=version)], - execution_command="%executable% -b -nolist -i %file:input_deck%" + execution_command="%executable% -b -nolist -i %file:inp%" " -o solve.out -np %resource:num_cores%", max_execution_time=360.0, resource_requirements=ResourceRequirements( num_cores=NUM_CORES, + distributed=True, ), execution_level=0, num_trials=1, - input_file_ids=[file_ids["input_deck"]], - output_file_ids=[id for name, id in file_ids.items() if name != "input_deck"], + input_file_ids=[file_ids["inp"]], + output_file_ids=[id for name, id in file_ids.items() if name != "inp"], ) - task_def = project_api.create_task_definitions([task_def])[0] + + if use_exec_script: + exec_script_file = project_api.copy_default_execution_script( + f"mapdl-v{version[2:4]}{version[6]}-exec_mapdl.py" + ) + + task_def.use_execution_script = True + task_def.execution_script_id = exec_script_file.id + + task_defs.append(task_def) + + task_def = project_api.create_task_definitions(task_defs)[0] return task_def.id, [f for f in files if f.name in ["rst", "ldhi", "Rnn", "rdb"]] def create_modal_task_definition( - project_api: ProjectApi, prestress_files: List[File], version: str + project_api: ProjectApi, prestress_files: List[File], use_exec_script: bool, version: str ) -> Tuple[str, List[File]]: log.info("=== Files") @@ -118,7 +131,7 @@ def create_modal_task_definition( # the prestress output files already exist, no need to create them files = [ File( - name="input_deck", + name="inp", evaluation_path="modal.dat", type="text/plain", src=os.path.join(cwd, "modal.dat"), @@ -170,30 +183,43 @@ def create_modal_task_definition( file_ids = {f.name: f.id for f in files} # Process step - input_file_ids = [file_ids["input_deck"]] + input_file_ids = [file_ids["inp"]] input_file_ids.extend([f.id for f in prestress_files]) + task_defs = [] task_def = TaskDefinition( name="Modal", software_requirements=[Software(name="Ansys Mechanical APDL", version=version)], - execution_command="%executable% -b -nolist -i %file:input_deck% " + execution_command="%executable% -b -nolist -i %file:inp% " "-o solve.out -np %resource:num_cores%", max_execution_time=360.0, resource_requirements=ResourceRequirements( num_cores=NUM_CORES, + distributed=True, ), execution_level=1, num_trials=1, input_file_ids=input_file_ids, - output_file_ids=[id for name, id in file_ids.items() if name != "input_deck"], + output_file_ids=[id for name, id in file_ids.items() if name != "inp"], ) - task_def = project_api.create_task_definitions([task_def])[0] + + if use_exec_script: + exec_script_file = project_api.copy_default_execution_script( + f"mapdl-v{version[2:4]}{version[6]}-exec_mapdl.py" + ) + + task_def.use_execution_script = True + task_def.execution_script_id = exec_script_file.id + + task_defs.append(task_def) + + task_def = project_api.create_task_definitions(task_defs)[0] return task_def.id, [f for f in files if f.name in ["rst", "mode", "db", "esav", "emat"]] def create_harmonic_task_definition( - project_api: ProjectApi, modal_files: List[File], version: str + project_api: ProjectApi, modal_files: List[File], use_exec_script: bool, version: str ) -> str: log.info("=== Files") @@ -202,7 +228,7 @@ def create_harmonic_task_definition( files = [ File( - name="input_deck", + name="inp", evaluation_path="harmonic.dat", type="text/plain", src=os.path.join(cwd, "harmonic.dat"), @@ -219,25 +245,37 @@ def create_harmonic_task_definition( file_ids = {f.name: f.id for f in files} # Process step - input_file_ids = [file_ids["input_deck"]] + input_file_ids = [file_ids["inp"]] input_file_ids.extend([f.id for f in modal_files]) + task_defs = [] task_def = TaskDefinition( name="Harmonic", software_requirements=[Software(name="Ansys Mechanical APDL", version=version)], - execution_command="%executable% -b -nolist -i %file:input_deck% " + execution_command="%executable% -b -nolist -i %file:inp% " "-o solve.out -np %resource:num_cores%", max_execution_time=360.0, resource_requirements=ResourceRequirements( num_cores=NUM_CORES, + distributed=True, ), execution_level=2, num_trials=1, input_file_ids=input_file_ids, - output_file_ids=[id for name, id in file_ids.items() if name != "input_deck"], + output_file_ids=[id for name, id in file_ids.items() if name != "inp"], ) - task_def = project_api.create_task_definitions([task_def])[0] + if use_exec_script: + exec_script_file = project_api.copy_default_execution_script( + f"mapdl-v{version[2:4]}{version[6]}-exec_mapdl.py" + ) + + task_def.use_execution_script = True + task_def.execution_script_id = exec_script_file.id + + task_defs.append(task_def) + + task_def = project_api.create_task_definitions(task_defs)[0] return task_def.id @@ -248,7 +286,9 @@ def set_last_task_to_pending(project_api: ProjectApi, job_id: str): return project_api.update_tasks([task]) -def create_project(client: Client, name: str, incremental: bool, version: str) -> Project: +def create_project( + client: Client, name: str, incremental: bool, use_exec_script: bool, version: str +) -> Project: log.info("=== REP connection") log.info(f"Client connected at {client.rep_url}") @@ -267,7 +307,9 @@ def create_project(client: Client, name: str, incremental: bool, version: str) - job_definition = JobDefinition(name="Linked Analyses", active=True) log.info("=== Create Prestress task definition") - prestress_task_def_id, prestress_files = create_prestress_task_definition(project_api, version) + prestress_task_def_id, prestress_files = create_prestress_task_definition( + project_api, use_exec_script, version + ) job_definition.task_definition_ids = [prestress_task_def_id] @@ -281,7 +323,7 @@ def create_project(client: Client, name: str, incremental: bool, version: str) - log.info("=== Create Modal task definition") modal_task_def_id, modal_files = create_modal_task_definition( - project_api, prestress_files, version + project_api, prestress_files, use_exec_script, version ) job_definition.task_definition_ids.append(modal_task_def_id) @@ -293,7 +335,9 @@ def create_project(client: Client, name: str, incremental: bool, version: str) - set_last_task_to_pending(project_api, job.id) log.info("=== Create Harmonic task definition") - harmonic_task_def_id = create_harmonic_task_definition(project_api, modal_files, version) + harmonic_task_def_id = create_harmonic_task_definition( + project_api, modal_files, use_exec_script, version + ) job_definition.task_definition_ids.append(harmonic_task_def_id) @@ -317,6 +361,7 @@ def create_project(client: Client, name: str, incremental: bool, version: str) - if __name__ == "__main__": parser = argparse.ArgumentParser() parser.add_argument("-n", "--name", type=str, default="MAPDL Prestress-Modal-Harmonic") + parser.add_argument("-es", "--use-exec-script", default=False, type=bool) parser.add_argument("-U", "--url", default="https://localhost:8443/rep") parser.add_argument("-u", "--username", default="repadmin") parser.add_argument("-p", "--password", default="repadmin") @@ -333,7 +378,11 @@ def create_project(client: Client, name: str, incremental: bool, version: str) - try: create_project( - client, name=args.name, incremental=args.incremental, version=args.ansys_version + client, + name=args.name, + incremental=args.incremental, + use_exec_script=args.use_exec_script, + version=args.ansys_version, ) except REPError as e: log.error(str(e)) diff --git a/examples/mapdl_tyre_performance/project_setup.py b/examples/mapdl_tyre_performance/project_setup.py index 64894aa8..a5343ccb 100644 --- a/examples/mapdl_tyre_performance/project_setup.py +++ b/examples/mapdl_tyre_performance/project_setup.py @@ -28,7 +28,9 @@ log = logging.getLogger(__name__) -def main(client: Client, name: str, num_jobs: int, version: str) -> Project: +def create_project( + client, name, version=__ansys_apps_version__, num_jobs=20, use_exec_script=False, active=True +) -> Project: log.debug("=== Project") jms_api = JmsApi(client) @@ -42,7 +44,7 @@ def main(client: Client, name: str, num_jobs: int, version: str) -> Project: files = [ File( - name="mac", + name="inp", evaluation_path="tire_performance_simulation.mac", type="text/plain", src=os.path.join(cwd, "tire_performance_simulation.mac"), @@ -123,25 +125,25 @@ def main(client: Client, name: str, num_jobs: int, version: str) -> Project: key_string="camber_angle", tokenizer="=", parameter_definition_id=input_params[0].id, - file_id=file_ids["mac"], + file_id=file_ids["inp"], ), ParameterMapping( key_string="inflation_pressure", tokenizer="=", parameter_definition_id=input_params[1].id, - file_id=file_ids["mac"], + file_id=file_ids["inp"], ), ParameterMapping( key_string="rotational_velocity", tokenizer="=", parameter_definition_id=input_params[2].id, - file_id=file_ids["mac"], + file_id=file_ids["inp"], ), ParameterMapping( key_string="translational_velocity", tokenizer="=", parameter_definition_id=input_params[3].id, - file_id=file_ids["mac"], + file_id=file_ids["inp"], ), ] @@ -174,11 +176,12 @@ def main(client: Client, name: str, num_jobs: int, version: str) -> Project: # TODO, add more + task_defs = [] # Process step task_def = TaskDefinition( name="MAPDL_run", software_requirements=[Software(name="Ansys Mechanical APDL", version=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( num_cores=4, memory=4000 * 1024 * 1024, @@ -191,7 +194,18 @@ def main(client: Client, name: str, num_jobs: int, version: str) -> Project: input_file_ids=[f.id for f in files[:2]], output_file_ids=[f.id for f in files[2:]], ) - task_def = project_api.create_task_definitions([task_def])[0] + + if use_exec_script: + exec_script_file = project_api.copy_default_execution_script( + f"mapdl-v{version[2:4]}{version[6]}-exec_mapdl.py" + ) + + task_def.use_execution_script = True + task_def.execution_script_id = exec_script_file.id + + task_defs.append(task_def) + + task_def = project_api.create_task_definitions(task_defs)[0] # Create job_definition in project job_def = JobDefinition(name="JobDefinition.1", active=True) @@ -226,6 +240,7 @@ def main(client: Client, name: str, num_jobs: int, version: str) -> Project: parser = argparse.ArgumentParser() parser.add_argument("-n", "--name", type=str, default="Mapdl Tyre Performance") parser.add_argument("-j", "--num-jobs", type=int, default=10) + parser.add_argument("-es", "--use-exec-script", default=False, type=bool) parser.add_argument("-U", "--url", default="https://localhost:8443/rep") parser.add_argument("-u", "--username", default="repadmin") parser.add_argument("-p", "--password", default="repadmin") @@ -240,6 +255,13 @@ def main(client: Client, name: str, num_jobs: int, version: str) -> Project: client = Client(rep_url=args.url, username=args.username, password=args.password) try: - main(client, name=args.name, num_jobs=args.num_jobs, version=args.ansys_version) + log.info(f"REP URL: {client.rep_url}") + proj = create_project( + client=client, + name=args.name, + version=args.ansys_version, + num_jobs=args.num_jobs, + use_exec_script=args.use_exec_script, + ) except REPError as e: log.error(str(e)) diff --git a/tests/test_examples.py b/tests/test_examples.py index 8aad0bde..a9a67949 100644 --- a/tests/test_examples.py +++ b/tests/test_examples.py @@ -74,10 +74,12 @@ def test_mapdl_motorbike_frame_with_user_defined_version(self): def test_mapdl_tyre_performance(self): - from examples.mapdl_tyre_performance.project_setup import main + from examples.mapdl_tyre_performance.project_setup import create_project num_jobs = 1 - project = main(self.client, f"Test mapdl_tyre_performance", num_jobs, version=ansys_version) + project = create_project( + self.client, f"Test mapdl_tyre_performance", ansys_version, num_jobs + ) self.assertIsNotNone(project) jms_api = JmsApi(self.client) @@ -128,6 +130,7 @@ def test_mapdl_linked_analyses(self): client, name="Test Linked Analyses", incremental=incremental_version, + use_exec_script=False, version=ansys_version, ) self.assertIsNotNone(project) @@ -142,9 +145,26 @@ def test_mapdl_linked_analyses(self): def test_fluent_2d_heat_exchanger(self): - from examples.fluent_2d_heat_exchanger.project_setup import main + from examples.fluent_2d_heat_exchanger.project_setup import create_project + + project = create_project(self.client, name="Fluent Test", version=ansys_version) + self.assertIsNotNone(project) + + jms_api = JmsApi(self.client) + project_api = ProjectApi(self.client, project.id) + + self.assertEqual(len(project_api.get_jobs()), 1) + self.assertEqual(jms_api.get_project(id=project.id).name, "Fluent Test") + + jms_api.delete_project(project) - project = main(self.client, name="Fluent Test", version=ansys_version) + def test_fluent_2d_heat_exchanger_with_exec_script(self): + + from examples.fluent_2d_heat_exchanger.project_setup import create_project + + project = create_project( + self.client, name="Fluent Test", version=ansys_version, use_exec_script=True + ) self.assertIsNotNone(project) jms_api = JmsApi(self.client) @@ -172,6 +192,38 @@ def test_fluent_nozzle(self): jms_api.delete_project(project) + def test_lsdyna_cylinder_plate(self): + + from examples.lsdyna_cylinder_plate.lsdyna_job import submit_job + + app_job = submit_job() + self.assertIsNotNone(app_job) + + jms_api = JmsApi(self.client) + project_api = ProjectApi(self.client, app_job.project_id) + + self.assertEqual(len(project_api.get_jobs()), 1) + proj = jms_api.get_project(id=app_job.project_id) + self.assertEqual(proj.name, "LS-DYNA Cylinder Plate") + + jms_api.delete_project(proj) + + def test_lsdyna_cylinder_plate_with_exec_script(self): + + from examples.lsdyna_cylinder_plate.lsdyna_job import submit_job + + app_job = submit_job(use_exec_script=True) + self.assertIsNotNone(app_job) + + jms_api = JmsApi(self.client) + project_api = ProjectApi(self.client, app_job.project_id) + + self.assertEqual(len(project_api.get_jobs()), 1) + proj = jms_api.get_project(id=app_job.project_id) + self.assertEqual(proj.name, "LS-DYNA Cylinder Plate") + + jms_api.delete_project(proj) + def test_cfx_static_mixer(self): from examples.cfx_static_mixer.project_setup import create_project