diff --git a/src/ansys/fluent/core/codegen/__init__.py b/src/ansys/fluent/core/codegen/__init__.py index 2dc876be6bf..75c74a2c028 100644 --- a/src/ansys/fluent/core/codegen/__init__.py +++ b/src/ansys/fluent/core/codegen/__init__.py @@ -18,3 +18,6 @@ class StaticInfoType(Enum): DATAMODEL_SOLVER_WORKFLOW = auto() DATAMODEL_MESHING_UTILITIES = auto() SETTINGS = auto() + + +CODEGEN_GENERATE_BUILTIN_SETTINGS = True diff --git a/src/ansys/fluent/core/codegen/allapigen.py b/src/ansys/fluent/core/codegen/allapigen.py index 0981b140209..2b78bb51eef 100644 --- a/src/ansys/fluent/core/codegen/allapigen.py +++ b/src/ansys/fluent/core/codegen/allapigen.py @@ -3,6 +3,7 @@ from pathlib import Path import pickle +from ansys.fluent.core import codegen from ansys.fluent.core.codegen import ( builtin_settingsgen, datamodelgen, @@ -10,6 +11,7 @@ tuigen, ) from ansys.fluent.core.search import get_api_tree_file_name +from ansys.fluent.core.utils.fluent_version import FluentVersion def _update_first_level(d, u): @@ -27,7 +29,10 @@ def generate(version: str, static_infos: dict): Path(api_tree_file).parent.mkdir(parents=True, exist_ok=True) with open(api_tree_file, "wb") as f: pickle.dump(api_tree, f) - builtin_settingsgen.generate() + if codegen.CODEGEN_GENERATE_BUILTIN_SETTINGS and FluentVersion(version) == next( + iter(FluentVersion) + ): + builtin_settingsgen.generate(version) if __name__ == "__main__": diff --git a/src/ansys/fluent/core/codegen/builtin_settingsgen.py b/src/ansys/fluent/core/codegen/builtin_settingsgen.py index 12b631a47b6..7ab5976222a 100644 --- a/src/ansys/fluent/core/codegen/builtin_settingsgen.py +++ b/src/ansys/fluent/core/codegen/builtin_settingsgen.py @@ -1,19 +1,46 @@ """Generate builtin setting classes.""" from ansys.fluent.core import CODEGEN_OUTDIR, FluentVersion +from ansys.fluent.core.solver.flobject import CreatableNamedObjectMixin from ansys.fluent.core.solver.settings_builtin_data import DATA _PY_FILE = CODEGEN_OUTDIR / "solver" / "settings_builtin.py" _PYI_FILE = CODEGEN_OUTDIR / "solver" / "settings_builtin.pyi" -def generate(): +def _get_settings_root(version: str): + from ansys.fluent.core import CODEGEN_OUTDIR, CODEGEN_ZIP_SETTINGS, utils + + if CODEGEN_ZIP_SETTINGS: + importer = zipimporter( + str(CODEGEN_OUTDIR / "solver" / f"settings_{version}.zip") + ) + settings = importer.load_module("settings") + else: + settings = utils.load_module( + f"settings_{version}", + CODEGEN_OUTDIR / "solver" / f"settings_{version}" / "__init__.py", + ) + return settings.root + + +def _get_named_object_type(root, path): + for comp in path.split("."): + root = root._child_classes[comp] + return ( + "Creatable" if issubclass(root, CreatableNamedObjectMixin) else "NonCreatable" + ) + + +def generate(version: str): """Generate builtin setting classes.""" + print("Generating builtin settings...") CODEGEN_OUTDIR.mkdir(exist_ok=True) + root = _get_settings_root(version) with open(_PY_FILE, "w") as f: f.write('"""Solver settings."""\n\n') f.write( - "from ansys.fluent.core.solver.settings_builtin_bases import _SingletonSetting, _NamedObjectSetting\n\n\n" + "from ansys.fluent.core.solver.settings_builtin_bases import _SingletonSetting, _CreatableNamedObjectSetting, _NonCreatableNamedObjectSetting\n\n\n" ) f.write("__all__ = [\n") for name, _ in DATA.items(): @@ -21,6 +48,9 @@ def generate(): f.write("]\n\n") for name, v in DATA.items(): kind, path = v + if kind == "NamedObject": + path = path[FluentVersion(version)] if isinstance(path, dict) else path + kind = f"{_get_named_object_type(root, path)}NamedObject" f.write(f"class {name}(_{kind}Setting):\n") f.write(f' """{name} setting."""\n\n') @@ -43,4 +73,5 @@ def generate(): if __name__ == "__main__": - generate() + version = "251" # for development + generate(version) diff --git a/src/ansys/fluent/core/codegen/tuigen.py b/src/ansys/fluent/core/codegen/tuigen.py index 6e9ab2e1614..d4a47a2c030 100644 --- a/src/ansys/fluent/core/codegen/tuigen.py +++ b/src/ansys/fluent/core/codegen/tuigen.py @@ -132,7 +132,7 @@ def _populate_xml_helpstrings(): else: v = "".join(node.find("p").itertext()) _XML_HELPSTRINGS[k] = v - _XML_HELP_FILE.unlink() + _XML_HELP_FILE.unlink(missing_ok=True) def _is_valid_tui_menu_name(name): @@ -303,6 +303,11 @@ def generate(version, static_infos: dict): api_tree = {} gt_222 = FluentVersion(version) > FluentVersion.v222 if gt_222: + if ( + StaticInfoType.TUI_MESHING not in static_infos + and StaticInfoType.TUI_SOLVER not in static_infos + ): + return api_tree _copy_tui_help_xml_file(version) _populate_xml_helpstrings() if not gt_222 or StaticInfoType.TUI_MESHING in static_infos: diff --git a/src/ansys/fluent/core/solver/settings_builtin_bases.py b/src/ansys/fluent/core/solver/settings_builtin_bases.py index e5084bd9c53..9ba275a37ca 100644 --- a/src/ansys/fluent/core/solver/settings_builtin_bases.py +++ b/src/ansys/fluent/core/solver/settings_builtin_bases.py @@ -1,5 +1,7 @@ """Base classes for builtin setting classes.""" +from typing import Optional + from ansys.fluent.core.session_solver import Solver from ansys.fluent.core.solver.settings_builtin_data import DATA @@ -20,7 +22,25 @@ def __new__(cls, solver: Solver): return obj -class _NamedObjectSetting(_SingletonSetting): +class _CreatableNamedObjectSetting(_SingletonSetting): + def __new__( + cls, + solver: Solver, + name: Optional[str] = None, + new_instance_name: Optional[str] = None, + ): + if name and new_instance_name: + raise ValueError("Cannot specify both name and new_instance_name.") + obj = super().__new__(cls, solver) + if name: + return obj[name] + elif new_instance_name: + return obj.create(new_instance_name) + else: + return obj.create() + + +class _NonCreatableNamedObjectSetting(_SingletonSetting): def __new__(cls, solver: Solver, name: str): obj = super().__new__(cls, solver) return obj[name] diff --git a/src/ansys/fluent/core/solver/settings_builtin_data.py b/src/ansys/fluent/core/solver/settings_builtin_data.py index 77c96dff2cc..c5103c15047 100644 --- a/src/ansys/fluent/core/solver/settings_builtin_data.py +++ b/src/ansys/fluent/core/solver/settings_builtin_data.py @@ -142,12 +142,6 @@ "SolidMaterial": ("NamedObject", "setup.materials.solid"), "MixtureMaterials": ("Singleton", "setup.materials.mixture"), "MixtureMaterial": ("NamedObject", "setup.materials.mixture"), - "InertParticles": ("Singleton", "setup.materials.inert_particles"), - "InertParticle": ("NamedObject", "setup.materials.inert_particles"), - "DropletParticles": ("Singleton", "setup.materials.droplet_particles"), - "DropletParticle": ("NamedObject", "setup.materials.droplet_particles"), - "CombustingParticles": ("Singleton", "setup.materials.combusting_particles"), - "CombustingParticle": ("NamedObject", "setup.materials.combusting_particles"), "ParticleMixtureMaterials": ("Singleton", "setup.materials.particle_mixture"), "ParticleMixtureMaterial": ("NamedObject", "setup.materials.particle_mixture"), "CellZoneConditions": ("Singleton", "setup.cell_zone_conditions"), @@ -260,19 +254,35 @@ "WallBoundary": ("NamedObject", "setup.boundary_conditions.wall"), "NonReflectingBoundaries": ( "Singleton", - "setup.boundary_conditions.non_reflecting_bc", + { + FluentVersion.v251: "setup.boundary_conditions.non_reflecting_bc", + FluentVersion.v242: "setup.boundary_conditions.non_reflecting_bc", + FluentVersion.v241: "setup.boundary_conditions.non_reflecting_bc", + }, ), "NonReflectingBoundary": ( "NamedObject", - "setup.boundary_conditions.non_reflecting_bc", + { + FluentVersion.v251: "setup.boundary_conditions.non_reflecting_bc", + FluentVersion.v242: "setup.boundary_conditions.non_reflecting_bc", + FluentVersion.v241: "setup.boundary_conditions.non_reflecting_bc", + }, ), "PerforatedWallBoundaries": ( "Singleton", - "setup.boundary_conditions.perforated_wall", + { + FluentVersion.v251: "setup.boundary_conditions.perforated_wall", + FluentVersion.v242: "setup.boundary_conditions.perforated_wall", + FluentVersion.v241: "setup.boundary_conditions.perforated_wall", + }, ), "PerforatedWallBoundary": ( "NamedObject", - "setup.boundary_conditions.perforated_wall", + { + FluentVersion.v251: "setup.boundary_conditions.perforated_wall", + FluentVersion.v242: "setup.boundary_conditions.perforated_wall", + FluentVersion.v241: "setup.boundary_conditions.perforated_wall", + }, ), "MeshInterfaces": ( "Singleton", @@ -321,4 +331,125 @@ FluentVersion.v232: "setup.named_expressions", }, ), + "Methods": ("Singleton", "solution.methods"), + "Controls": ("Singleton", "solution.controls"), + "ReportDefinitions": ("Singleton", "solution.report_definitions"), + "Monitor": ( + "Singleton", + { + FluentVersion.v251: "solution.monitor", + FluentVersion.v242: "solution.monitor", + FluentVersion.v241: "solution.monitor", + FluentVersion.v232: "solution.monitor", + FluentVersion.v231: "solution.monitor", + }, + ), + "Residual": ( + "Singleton", + { + FluentVersion.v251: "solution.monitor.residual", + FluentVersion.v242: "solution.monitor.residual", + FluentVersion.v241: "solution.monitor.residual", + }, + ), + "ReportFiles": ( + "Singleton", + { + FluentVersion.v251: "solution.monitor.report_files", + FluentVersion.v242: "solution.monitor.report_files", + FluentVersion.v241: "solution.monitor.report_files", + FluentVersion.v232: "solution.monitor.report_files", + FluentVersion.v231: "solution.monitor.report_files", + }, + ), + "ReportFile": ( + "NamedObject", + { + FluentVersion.v251: "solution.monitor.report_files", + FluentVersion.v242: "solution.monitor.report_files", + FluentVersion.v241: "solution.monitor.report_files", + FluentVersion.v232: "solution.monitor.report_files", + FluentVersion.v231: "solution.monitor.report_files", + }, + ), + "ReportPlots": ( + "Singleton", + { + FluentVersion.v251: "solution.monitor.report_plots", + FluentVersion.v242: "solution.monitor.report_plots", + FluentVersion.v241: "solution.monitor.report_plots", + FluentVersion.v232: "solution.monitor.report_plots", + FluentVersion.v231: "solution.monitor.report_plots", + }, + ), + "ReportPlot": ( + "NamedObject", + { + FluentVersion.v251: "solution.monitor.report_plots", + FluentVersion.v242: "solution.monitor.report_plots", + FluentVersion.v241: "solution.monitor.report_plots", + FluentVersion.v232: "solution.monitor.report_plots", + FluentVersion.v231: "solution.monitor.report_plots", + }, + ), + "ConvergenceConditions": ( + "Singleton", + { + FluentVersion.v251: "solution.monitor.convergence_conditions", + FluentVersion.v242: "solution.monitor.convergence_conditions", + FluentVersion.v241: "solution.monitor.convergence_conditions", + FluentVersion.v232: "solution.monitor.convergence_conditions", + FluentVersion.v231: "solution.monitor.convergence_conditions", + }, + ), + "CellRegisters": ( + "Singleton", + { + FluentVersion.v251: "solution.cell_registers", + FluentVersion.v242: "solution.cell_registers", + FluentVersion.v241: "solution.cell_registers", + FluentVersion.v232: "solution.cell_registers", + FluentVersion.v231: "solution.cell_registers", + }, + ), + "CellRegister": ( + "NamedObject", + { + FluentVersion.v251: "solution.cell_registers", + FluentVersion.v242: "solution.cell_registers", + FluentVersion.v241: "solution.cell_registers", + FluentVersion.v232: "solution.cell_registers", + FluentVersion.v231: "solution.cell_registers", + }, + ), + "Initialization": ("Singleton", "solution.initialization"), + "CalculationActivity": ( + "Singleton", + { + FluentVersion.v251: "solution.calculation_activity", + FluentVersion.v242: "solution.calculation_activity", + FluentVersion.v241: "solution.calculation_activity", + FluentVersion.v232: "solution.calculation_activity", + FluentVersion.v231: "solution.calculation_activity", + }, + ), + "ExecuteCommands": ( + "Singleton", + { + FluentVersion.v251: "solution.calculation_activity.execute_commands", + FluentVersion.v242: "solution.calculation_activity.execute_commands", + FluentVersion.v241: "solution.calculation_activity.execute_commands", + FluentVersion.v232: "solution.calculation_activity.execute_commands", + FluentVersion.v231: "solution.calculation_activity.execute_commands", + }, + ), + "CaseModification": ( + "Singleton", + { + FluentVersion.v251: "solution.calculation_activity.case_modification", + FluentVersion.v242: "solution.calculation_activity.case_modification", + FluentVersion.v241: "solution.calculation_activity.case_modification", + }, + ), + "RunCalculation": ("Singleton", "solution.run_calculation"), } diff --git a/tests/conftest.py b/tests/conftest.py index 97515f69f7c..c1baafbebd8 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -8,6 +8,7 @@ import pytest import ansys.fluent.core as pyfluent +from ansys.fluent.core import codegen from ansys.fluent.core.examples.downloads import download_file from ansys.fluent.core.utils.file_transfer_service import RemoteFileTransferStrategy from ansys.fluent.core.utils.fluent_version import FluentVersion @@ -73,6 +74,7 @@ def run_before_each_test( monkeypatch.setenv("PYFLUENT_TEST_NAME", request.node.name) pyfluent.CONTAINER_MOUNT_SOURCE = pyfluent.EXAMPLES_PATH pyfluent.CONTAINER_MOUNT_TARGET = pyfluent.EXAMPLES_PATH + codegen.CODEGEN_GENERATE_BUILTIN_SETTINGS = False class Helpers: diff --git a/tests/test_settings_api.py b/tests/test_settings_api.py index e7a9efae298..a6098fb5851 100644 --- a/tests/test_settings_api.py +++ b/tests/test_settings_api.py @@ -509,23 +509,33 @@ def test_builtin_settings(static_mixer_case_session): Battery, BoundaryCondition, BoundaryConditions, + CalculationActivity, + CaseModification, + CellRegister, + CellRegisters, CellZoneCondition, CellZoneConditions, + Controls, + ConvergenceConditions, DiscretePhase, DynamicMesh, EChemistry, Energy, + ExecuteCommands, FluidCellZone, FluidCellZones, FluidMaterial, FluidMaterials, General, + Initialization, Injections, InteriorBoundaries, InteriorBoundary, Materials, MeshInterfaces, + Methods, Models, + Monitor, Multiphase, NamedExpressions, Optics, @@ -536,6 +546,13 @@ def test_builtin_settings(static_mixer_case_session): ReferenceFrame, ReferenceFrames, ReferenceValues, + ReportDefinitions, + ReportFile, + ReportFiles, + ReportPlot, + ReportPlots, + Residual, + RunCalculation, Setup, Sofc, SolidMaterial, @@ -687,6 +704,8 @@ def test_builtin_settings(static_mixer_case_session): WallBoundary(solver=solver, name="wall") == solver.setup.boundary_conditions.wall["wall"] ) + with pytest.raises(TypeError): + WallBoundary(solver=solver, new_instance_name="wall-1") if solver.get_fluent_version() >= FluentVersion.v232: assert MeshInterfaces(solver=solver) == solver.setup.mesh_interfaces else: @@ -718,3 +737,87 @@ def test_builtin_settings(static_mixer_case_session): else: with pytest.raises(RuntimeError): NamedExpressions(solver=solver) + assert Methods(solver=solver) == solver.solution.methods + assert Controls(solver=solver) == solver.solution.controls + assert ReportDefinitions(solver=solver) == solver.solution.report_definitions + if solver.get_fluent_version() >= FluentVersion.v231: + assert Monitor(solver=solver) == solver.solution.monitor + if solver.get_fluent_version() >= FluentVersion.v241: + assert Residual(solver=solver) == solver.solution.monitor.residual + else: + with pytest.raises(RuntimeError): + Residual(solver=solver) + assert ReportFiles(solver=solver) == solver.solution.monitor.report_files + assert ( + ReportFile(solver=solver, new_instance_name="report-file-1") + == solver.solution.monitor.report_files["report-file-1"] + ) + assert ( + ReportFile(solver=solver, name="report-file-1") + == solver.solution.monitor.report_files["report-file-1"] + ) + if solver.get_fluent_version() >= FluentVersion.v251: + assert ( + ReportFile(solver=solver) + == solver.solution.monitor.report_files["report-file-2"] + ) + assert ReportPlots(solver=solver) == solver.solution.monitor.report_plots + assert ( + ReportPlot(solver=solver, new_instance_name="report-plot-1") + == solver.solution.monitor.report_plots["report-plot-1"] + ) + assert ( + ReportPlot(solver=solver, name="report-plot-1") + == solver.solution.monitor.report_plots["report-plot-1"] + ) + if solver.get_fluent_version() >= FluentVersion.v251: + assert ( + ReportPlot(solver=solver) + == solver.solution.monitor.report_plots["report-plot-2"] + ) + assert ( + ConvergenceConditions(solver=solver) + == solver.solution.monitor.convergence_conditions + ) + else: + with pytest.raises(RuntimeError): + Monitor(solver=solver) + if solver.get_fluent_version() >= FluentVersion.v231: + assert CellRegisters(solver=solver) == solver.solution.cell_registers + assert ( + CellRegister(solver=solver, new_instance_name="cell_register_1") + == solver.solution.cell_registers["cell_register_1"] + ) + assert ( + CellRegister(solver=solver, name="cell_register_1") + == solver.solution.cell_registers["cell_register_1"] + ) + if solver.get_fluent_version() >= FluentVersion.v251: + assert ( + CellRegister(solver=solver) + == solver.solution.cell_registers["cell_register_2"] + ) + else: + with pytest.raises(RuntimeError): + CellRegisters(solver=solver) + assert Initialization(solver=solver) == solver.solution.initialization + if solver.get_fluent_version() >= FluentVersion.v231: + assert ( + CalculationActivity(solver=solver) == solver.solution.calculation_activity + ) + assert ( + ExecuteCommands(solver=solver) + == solver.solution.calculation_activity.execute_commands + ) + if solver.get_fluent_version() >= FluentVersion.v241: + assert ( + CaseModification(solver=solver) + == solver.solution.calculation_activity.case_modification + ) + else: + with pytest.raises(RuntimeError): + CaseModification(solver=solver) + else: + with pytest.raises(RuntimeError): + CalculationActivity(solver=solver) + assert RunCalculation(solver=solver) == solver.solution.run_calculation