diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 53f536b1f..0ca460bd0 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -3,9 +3,9 @@ name: unit testing on: workflow_dispatch: push: - branches: [ develop, main, release-candidate/* ] + branches: [ develop, main, release-candidate/*, BenY/OrganizingAndDocumentation ] pull_request: - branches: [ develop, main, release-candidate/* ] + branches: [ develop, main, release-candidate/*, BenY/OrganizingAndDocumentation ] workflow_call: jobs: diff --git a/examples/case_from_multiple_files/main.py b/examples/case_from_multiple_files/main.py index c22927834..d5bd6bf79 100644 --- a/examples/case_from_multiple_files/main.py +++ b/examples/case_from_multiple_files/main.py @@ -1,7 +1,7 @@ import os -import flow360 as fl -import flow360.component.flow360_params.units as u +import flow360.component.v1.units as u +import flow360.v1 as fl from flow360.examples import OM6wing here = os.path.dirname(os.path.abspath(__file__)) diff --git a/examples/case_from_yaml.py b/examples/case_from_yaml.py index d9a38ba63..e2931473e 100644 --- a/examples/case_from_yaml.py +++ b/examples/case_from_yaml.py @@ -1,4 +1,4 @@ -import flow360 as fl +import flow360.v1 as fl from flow360.examples import OM6wing OM6wing.get_files() diff --git a/examples/case_params_with_units.py b/examples/case_params_with_units.py index bc72aa3c7..29ace249e 100644 --- a/examples/case_params_with_units.py +++ b/examples/case_params_with_units.py @@ -1,10 +1,10 @@ import json from pprint import pprint -import flow360 as fl +import flow360.v1 as fl from flow360 import log -from flow360 import units as u -from flow360.component.flow360_params.services import validate_model +from flow360.component.v1 import units as u +from flow360.component.v1.services import validate_model log.set_logging_level("DEBUG") diff --git a/examples/change_account_and_submit.py b/examples/change_account_and_submit.py index 20cf19897..319b4312b 100644 --- a/examples/change_account_and_submit.py +++ b/examples/change_account_and_submit.py @@ -1,4 +1,4 @@ -import flow360 as fl +import flow360.v1 as fl from flow360.examples import OM6wing fl.Env.dev.active() diff --git a/examples/data/airplane_simple/airplane_simple.lb8.ugrid b/examples/data/airplane_simple/airplane_simple.lb8.ugrid deleted file mode 100644 index 90d0704f6..000000000 Binary files a/examples/data/airplane_simple/airplane_simple.lb8.ugrid and /dev/null differ diff --git a/examples/dev/dev_run_case_from_files.py b/examples/dev/dev_run_case_from_files.py index 2243a4656..6cda2fdc4 100644 --- a/examples/dev/dev_run_case_from_files.py +++ b/examples/dev/dev_run_case_from_files.py @@ -1,4 +1,4 @@ -import flow360 as fl +import flow360.v1 as fl from flow360.examples import OM6wing fl.Env.dev.active() diff --git a/examples/dev/dev_run_case_from_files_no_validation.py b/examples/dev/dev_run_case_from_files_no_validation.py index e5e0b2d7c..fda7ae454 100644 --- a/examples/dev/dev_run_case_from_files_no_validation.py +++ b/examples/dev/dev_run_case_from_files_no_validation.py @@ -1,6 +1,6 @@ import os -import flow360 as fl +import flow360.v1 as fl from flow360.examples import OM6wing fl.UserConfig.disable_validation() diff --git a/examples/dev/dev_update_models.py b/examples/dev/dev_update_models.py index f0858b010..ffa85d8a0 100644 --- a/examples/dev/dev_update_models.py +++ b/examples/dev/dev_update_models.py @@ -1,6 +1,6 @@ import os -from flow360.component.flow360_params.flow360_params import Flow360ParamsLegacy +from flow360.component.v1.flow360_params import Flow360ParamsLegacy here = os.path.dirname(os.path.abspath(__file__)) path = os.path.join(here, "../../flow360/examples/rotatingSpheres/flow360.json") diff --git a/examples/dev/dev_use_unit_system.py b/examples/dev/dev_use_unit_system.py index a52da3cb6..9e748129c 100644 --- a/examples/dev/dev_use_unit_system.py +++ b/examples/dev/dev_use_unit_system.py @@ -6,10 +6,9 @@ import pydantic.v1 as pd import unyt -import flow360 as fl -from flow360 import Geometry -from flow360 import units as u -from flow360.component.flow360_params.unit_system import ( +import flow360.v1 as fl +from flow360.component.v1 import units as u +from flow360.component.v1.unit_system import ( AngularVelocityType, AreaType, BaseSystemType, @@ -23,6 +22,7 @@ VelocityType, ViscosityType, ) +from flow360.v1 import Geometry class DataWithUnits(pd.BaseModel): diff --git a/examples/dev/dev_validate_params.py b/examples/dev/dev_validate_params.py index 3c9954b1b..4f265133b 100644 --- a/examples/dev/dev_validate_params.py +++ b/examples/dev/dev_validate_params.py @@ -1,7 +1,7 @@ import os import re -from flow360.component.flow360_params.flow360_params import Flow360ParamsLegacy +from flow360.component.v1.flow360_params import Flow360ParamsLegacy rootdir = "../../tests/data/cases/" regex = re.compile(r"(case_.*\.json$)") diff --git a/examples/dev/dev_webservice_usage.py b/examples/dev/dev_webservice_usage.py index e039b2bc0..0ce745b20 100644 --- a/examples/dev/dev_webservice_usage.py +++ b/examples/dev/dev_webservice_usage.py @@ -2,7 +2,7 @@ import os import re -from flow360.component.flow360_params.services import get_default_fork +from flow360.component.v1.services import get_default_fork # Webservice examples diff --git a/examples/dev/list_cases_all_params.py b/examples/dev/list_cases_all_params.py index 1acbd25d9..67635dd81 100644 --- a/examples/dev/list_cases_all_params.py +++ b/examples/dev/list_cases_all_params.py @@ -1,4 +1,4 @@ -import flow360 as fl +import flow360.v1 as fl from flow360.exceptions import Flow360ValidationError for case in fl.MyCases(limit=10000): diff --git a/examples/display_mesh_info.py b/examples/display_mesh_info.py index b359d031e..ba12291ea 100644 --- a/examples/display_mesh_info.py +++ b/examples/display_mesh_info.py @@ -1,4 +1,4 @@ -import flow360 as fl +import flow360.v1 as fl meshes = fl.MyVolumeMeshes() mesh = meshes[0] diff --git a/examples/geometry_id_surface_volume_case_airplane_v1_from_csm.py b/examples/geometry_id_surface_volume_case_airplane_v1_from_csm.py deleted file mode 100644 index ac460c705..000000000 --- a/examples/geometry_id_surface_volume_case_airplane_v1_from_csm.py +++ /dev/null @@ -1,56 +0,0 @@ -import os - -import flow360 as fl - -fl.Env.preprod.active() - -from flow360.component.geometry_v1 import Geometry -from flow360.component.meshing.params import Farfield, Volume, VolumeMeshingParams -from flow360.examples import Airplane - -# geometry -geometry_draft = Geometry.from_file(Airplane.geometry, name="testing-airplane-csm-geometry") -geometry = geometry_draft.submit() -print(geometry) - -# surface mesh -params = fl.SurfaceMeshingParams(max_edge_length=0.16) - -surface_mesh_draft = fl.SurfaceMesh.create( - geometry_id=geometry.id, - params=params, - name="airplane-surface-mesh-from-geometry-id-v1", - solver_version="mesher-24.2.2", -) -surface_mesh = surface_mesh_draft.submit() - -print(surface_mesh) - -# volume mesh -params = fl.VolumeMeshingParams( - volume=Volume( - first_layer_thickness=1e-5, - growth_rate=1.2, - ), - farfield=Farfield(type="auto"), -) - -volume_mesh_draft = fl.VolumeMesh.create( - surface_mesh_id=surface_mesh.id, - name="airplane-volume-mesh-from-geometry-id-v1", - params=params, - solver_version="mesher-24.2.2", -) -volume_mesh = volume_mesh_draft.submit() -print(volume_mesh) - -# case -params = fl.Flow360Params(Airplane.case_json) -params.boundaries = { - "fluid/farfield": fl.FreestreamBoundary(), - "fluid/fuselage": fl.NoSlipWall(), - "fluid/leftWing": fl.NoSlipWall(), - "fluid/rightWing": fl.NoSlipWall(), -} -case_draft = volume_mesh.create_case("airplane-case-from-csm-geometry-id-v1", params) -case = case_draft.submit() diff --git a/examples/geometry_id_surface_volume_case_airplane_v1_from_egads.py b/examples/geometry_id_surface_volume_case_airplane_v1_from_egads.py deleted file mode 100644 index fcdfcbf83..000000000 --- a/examples/geometry_id_surface_volume_case_airplane_v1_from_egads.py +++ /dev/null @@ -1,56 +0,0 @@ -import os - -import flow360 as fl - -fl.Env.preprod.active() - -from flow360.component.geometry_v1 import Geometry -from flow360.component.meshing.params import Farfield, Volume, VolumeMeshingParams -from flow360.examples import Airplane - -# geometry -geometry_draft = Geometry.from_file( - "data/airplane_geometry.egads", name="testing-airplane-egads-geometry" -) -geometry = geometry_draft.submit() -print(geometry) - -# surface mesh -params = fl.SurfaceMeshingParams(max_edge_length=0.16) - -surface_mesh_draft = fl.SurfaceMesh.create( - geometry_id=geometry.id, - params=params, - name="airplane-surface-mesh-from-geometry-id-v1", -) -surface_mesh = surface_mesh_draft.submit() - -print(surface_mesh) - -# volume mesh -params = fl.VolumeMeshingParams( - volume=Volume( - first_layer_thickness=1e-5, - growth_rate=1.2, - ), - farfield=Farfield(type="auto"), -) - -volume_mesh_draft = fl.VolumeMesh.create( - surface_mesh_id=surface_mesh.id, - name="airplane-volume-mesh-from-geometry-id-v1", - params=params, -) -volume_mesh = volume_mesh_draft.submit() -print(volume_mesh) - -# case -params = fl.Flow360Params(Airplane.case_json) -params.boundaries = { - "fluid/farfield": fl.FreestreamBoundary(), - "fluid/fuselage": fl.NoSlipWall(), - "fluid/leftWing": fl.NoSlipWall(), - "fluid/rightWing": fl.NoSlipWall(), -} -case_draft = volume_mesh.create_case("airplane-case-from-egads-geometry-id-v1", params) -case = case_draft.submit() diff --git a/examples/list_cases.py b/examples/list_cases.py index 182eff90c..cc5660487 100644 --- a/examples/list_cases.py +++ b/examples/list_cases.py @@ -1,4 +1,4 @@ -import flow360 as fl +import flow360.v1 as fl # get all cases: my_cases = fl.MyCases() diff --git a/examples/new_workbench_project_from_geometry.py b/examples/new_workbench_project_from_geometry.py index 5fb5261a8..c638b4dc0 100644 --- a/examples/new_workbench_project_from_geometry.py +++ b/examples/new_workbench_project_from_geometry.py @@ -1,4 +1,4 @@ -import flow360 as fl +import flow360.v1 as fl from flow360.component.geometry import Geometry from flow360.examples import Airplane diff --git a/examples/new_workbench_project_from_volume_mesh.py b/examples/new_workbench_project_from_volume_mesh.py index 556e67cbd..c4b7a8604 100644 --- a/examples/new_workbench_project_from_volume_mesh.py +++ b/examples/new_workbench_project_from_volume_mesh.py @@ -1,7 +1,7 @@ import time -import flow360 as fl import flow360.component.simulation.units as u +import flow360.v1 as fl from flow360.component.simulation.cloud import run_case from flow360.component.simulation.models.surface_models import ( Freestream, diff --git a/examples/project_from_file_geometry.py b/examples/project_from_file_geometry.py index e3923550c..2272e8955 100644 --- a/examples/project_from_file_geometry.py +++ b/examples/project_from_file_geometry.py @@ -1,4 +1,4 @@ -import flow360 as fl +import flow360.v1 as fl from flow360.component.project import Project from flow360.component.simulation.meshing_param.params import ( MeshingDefaults, diff --git a/examples/project_from_file_geometry_multiple_runs.py b/examples/project_from_file_geometry_multiple_runs.py index 254136c8b..bec713e1d 100644 --- a/examples/project_from_file_geometry_multiple_runs.py +++ b/examples/project_from_file_geometry_multiple_runs.py @@ -1,4 +1,4 @@ -import flow360 as fl +import flow360.v1 as fl from flow360.component.project import Project from flow360.component.simulation.meshing_param.params import ( MeshingDefaults, diff --git a/examples/project_from_file_volume_mesh.py b/examples/project_from_file_volume_mesh.py index 86c4b5089..b1afe07af 100644 --- a/examples/project_from_file_volume_mesh.py +++ b/examples/project_from_file_volume_mesh.py @@ -1,7 +1,7 @@ from matplotlib.pyplot import show -import flow360 as fl import flow360.component.simulation.units as u +import flow360.v1 as fl from flow360.component.project import Project from flow360.component.simulation.models.surface_models import ( Freestream, diff --git a/examples/retrieve_results/actuator_disk.py b/examples/retrieve_results/actuator_disk.py index 387529d5b..7ccf1393e 100644 --- a/examples/retrieve_results/actuator_disk.py +++ b/examples/retrieve_results/actuator_disk.py @@ -1,7 +1,7 @@ import os -import flow360 as fl import flow360.units as u +import flow360.v1 as fl from flow360.examples import ActuatorDisk ActuatorDisk.get_files() diff --git a/examples/retrieve_results/alpha_sweep.py b/examples/retrieve_results/alpha_sweep.py index fb65e7ff5..20e79ae9f 100644 --- a/examples/retrieve_results/alpha_sweep.py +++ b/examples/retrieve_results/alpha_sweep.py @@ -3,7 +3,7 @@ from pylab import plot, show, xlabel, ylabel -import flow360 as fl +import flow360.v1 as fl from flow360.examples import OM6wing OM6wing.get_files() diff --git a/examples/retrieve_results/bet_disk.py b/examples/retrieve_results/bet_disk.py index 8d0518515..e89c343d4 100644 --- a/examples/retrieve_results/bet_disk.py +++ b/examples/retrieve_results/bet_disk.py @@ -1,7 +1,7 @@ import os -import flow360 as fl -import flow360.component.flow360_params.units as u +import flow360.component.v1.units as u +import flow360.v1 as fl from flow360.examples import BETDisk BETDisk.get_files() diff --git a/examples/retrieve_results/convergence.py b/examples/retrieve_results/convergence.py index 31db6ab77..302a22b00 100644 --- a/examples/retrieve_results/convergence.py +++ b/examples/retrieve_results/convergence.py @@ -1,4 +1,4 @@ -import flow360 as fl +import flow360.v1 as fl from flow360.examples import Convergence Convergence.get_files() diff --git a/examples/retrieve_results/forces.py b/examples/retrieve_results/forces.py index 6382237d6..b6abcb5a2 100644 --- a/examples/retrieve_results/forces.py +++ b/examples/retrieve_results/forces.py @@ -1,4 +1,4 @@ -import flow360 as fl +import flow360.v1 as fl from flow360.examples import OM6wing OM6wing.get_files() diff --git a/examples/retrieve_results/monitors.py b/examples/retrieve_results/monitors.py index ccadd3302..e12228e78 100644 --- a/examples/retrieve_results/monitors.py +++ b/examples/retrieve_results/monitors.py @@ -1,4 +1,4 @@ -import flow360 as fl +import flow360.v1 as fl from flow360.examples import MonitorsAndSlices MonitorsAndSlices.get_files() diff --git a/examples/retrieve_results/user_defined_dynamics.py b/examples/retrieve_results/user_defined_dynamics.py index a1dab5ecc..08228abdd 100644 --- a/examples/retrieve_results/user_defined_dynamics.py +++ b/examples/retrieve_results/user_defined_dynamics.py @@ -1,6 +1,6 @@ from pylab import show -import flow360 as fl +import flow360.v1 as fl from flow360.examples import OM6wingUserDefinedDynamics OM6wingUserDefinedDynamics.get_files() diff --git a/examples/retrieve_results/volumetric_and_surface.py b/examples/retrieve_results/volumetric_and_surface.py index b63ef34c1..f9eeec7c6 100644 --- a/examples/retrieve_results/volumetric_and_surface.py +++ b/examples/retrieve_results/volumetric_and_surface.py @@ -2,7 +2,7 @@ import tarfile import tempfile -import flow360 as fl +import flow360.v1 as fl from flow360.examples import MonitorsAndSlices MonitorsAndSlices.get_files() diff --git a/examples/run_case_from_example_mesh.py b/examples/run_case_from_example_mesh.py index f1cb2a466..c7174d94d 100644 --- a/examples/run_case_from_example_mesh.py +++ b/examples/run_case_from_example_mesh.py @@ -1,4 +1,4 @@ -import flow360 as fl +import flow360.v1 as fl from flow360.examples import OM6wing vm = fl.VolumeMesh.copy_from_example("2ad77a88-1676-4f89-8652-13bd7e34f257") diff --git a/examples/run_case_from_files.py b/examples/run_case_from_files.py index 6b65ba53d..fafdc747b 100644 --- a/examples/run_case_from_files.py +++ b/examples/run_case_from_files.py @@ -1,4 +1,4 @@ -import flow360 as fl +import flow360.v1 as fl from flow360.examples import OM6wing OM6wing.get_files() diff --git a/examples/run_case_from_inputs.py b/examples/run_case_from_inputs.py index 5420f9adb..5455827b6 100644 --- a/examples/run_case_from_inputs.py +++ b/examples/run_case_from_inputs.py @@ -1,4 +1,4 @@ -import flow360 as fl +import flow360.v1 as fl from flow360.examples import OM6wing OM6wing.get_files() diff --git a/examples/run_case_no_submit_warning.py b/examples/run_case_no_submit_warning.py index 822c164d2..6b140a69a 100644 --- a/examples/run_case_no_submit_warning.py +++ b/examples/run_case_no_submit_warning.py @@ -1,4 +1,4 @@ -import flow360 as fl +import flow360.v1 as fl from flow360.examples import OM6wing OM6wing.get_files() diff --git a/examples/run_case_unsteady_from_files.py b/examples/run_case_unsteady_from_files.py index 14d4b3a20..8a14bc65b 100644 --- a/examples/run_case_unsteady_from_files.py +++ b/examples/run_case_unsteady_from_files.py @@ -1,4 +1,4 @@ -import flow360 as fl +import flow360.v1 as fl from flow360.examples import Cylinder2D Cylinder2D.get_files() diff --git a/examples/run_case_with_fork.py b/examples/run_case_with_fork.py index e03847042..299c5072f 100644 --- a/examples/run_case_with_fork.py +++ b/examples/run_case_with_fork.py @@ -1,4 +1,4 @@ -import flow360 as fl +import flow360.v1 as fl from flow360.examples import OM6wing OM6wing.get_files() diff --git a/examples/run_case_with_retry.py b/examples/run_case_with_retry.py index e9f765fac..66d8053e7 100644 --- a/examples/run_case_with_retry.py +++ b/examples/run_case_with_retry.py @@ -1,4 +1,4 @@ -import flow360 as fl +import flow360.v1 as fl from flow360.examples import OM6wing OM6wing.get_files() diff --git a/examples/show_storage.py b/examples/show_storage.py index 1a9414223..98036432a 100644 --- a/examples/show_storage.py +++ b/examples/show_storage.py @@ -1,4 +1,4 @@ -import flow360 as fl +import flow360.v1 as fl fl.Env.preprod.active() diff --git a/examples/submit_case_to_folder.py b/examples/submit_case_to_folder.py index 363349c98..eccf3c727 100644 --- a/examples/submit_case_to_folder.py +++ b/examples/submit_case_to_folder.py @@ -1,4 +1,4 @@ -import flow360 as fl +import flow360.v1 as fl from flow360.examples import OM6wing # create folder in ROOT level diff --git a/examples/surface_mesh_airplane_from_files.py b/examples/surface_mesh_airplane_from_files.py index 01e474c6e..2fc538a53 100644 --- a/examples/surface_mesh_airplane_from_files.py +++ b/examples/surface_mesh_airplane_from_files.py @@ -1,4 +1,4 @@ -import flow360 as fl +import flow360.v1 as fl from flow360.examples import Airplane params = fl.SurfaceMeshingParams(Airplane.surface_json) diff --git a/examples/surface_mesh_airplane_from_inputs.py b/examples/surface_mesh_airplane_from_inputs.py index 3b71b52ed..fe1d20f29 100644 --- a/examples/surface_mesh_airplane_from_inputs.py +++ b/examples/surface_mesh_airplane_from_inputs.py @@ -1,4 +1,4 @@ -import flow360 as fl +import flow360.v1 as fl from flow360.examples import Airplane params = fl.SurfaceMeshingParams( diff --git a/examples/surface_mesh_list.py b/examples/surface_mesh_list.py index e71e5bacd..5e816001d 100644 --- a/examples/surface_mesh_list.py +++ b/examples/surface_mesh_list.py @@ -1,4 +1,4 @@ -import flow360 as fl +import flow360.v1 as fl my_meshes = fl.MySurfaceMeshes() diff --git a/examples/volume_mesh_from_surface_mesh_files.py b/examples/volume_mesh_from_surface_mesh_files.py index 2b97b2e5e..44e931dd3 100644 --- a/examples/volume_mesh_from_surface_mesh_files.py +++ b/examples/volume_mesh_from_surface_mesh_files.py @@ -1,4 +1,4 @@ -import flow360 as fl +import flow360.v1 as fl from flow360.examples import Airplane params = fl.SurfaceMeshingParams(Airplane.surface_json) diff --git a/examples/volume_mesh_from_surface_mesh_inputs.py b/examples/volume_mesh_from_surface_mesh_inputs.py index 398f8a3e1..19427bef6 100644 --- a/examples/volume_mesh_from_surface_mesh_inputs.py +++ b/examples/volume_mesh_from_surface_mesh_inputs.py @@ -1,4 +1,4 @@ -import flow360 as fl +import flow360.v1 as fl from flow360.examples import Airplane params = fl.SurfaceMeshingParams( diff --git a/flow360/__init__.py b/flow360/__init__.py index bb647ff0c..a96d0c5fa 100644 --- a/flow360/__init__.py +++ b/flow360/__init__.py @@ -1,276 +1,213 @@ """ -This module is flow360. +This module is flow360 for simulation based models """ -import os - -from numpy import pi - -from flow360.component.flow360_params.unit_system import ( - CGS_unit_system, - SI_unit_system, - UnitSystem, - flow360_unit_system, - imperial_unit_system, +from flow360.accounts_utils import Accounts +from flow360.component.project import Project +from flow360.component.simulation import services +from flow360.component.simulation import units as u +from flow360.component.simulation.entity_info import GeometryEntityInfo +from flow360.component.simulation.meshing_param.edge_params import ( + AngleBasedRefinement, + AspectRatioBasedRefinement, + HeightBasedRefinement, + ProjectAnisoSpacing, + SurfaceEdgeRefinement, ) - -from . import global_exception_handler -from .accounts_utils import Accounts -from .cli import flow360 -from .cloud.s3_utils import ProgressCallbackInterface -from .component import meshing -from .component.case import Case -from .component.case import CaseList as MyCases -from .component.flow360_params import solvers, units -from .component.flow360_params.boundaries import ( - FreestreamBoundary, - HeatFluxWall, - IsothermalWall, - MassInflow, - MassOutflow, - NoSlipWall, - PressureOutflow, - RiemannInvariant, - RotationallyPeriodic, - SlidingInterfaceBoundary, +from flow360.component.simulation.meshing_param.face_params import ( + BoundaryLayer, + PassiveSpacing, + SurfaceRefinement, +) +from flow360.component.simulation.meshing_param.params import ( + MeshingDefaults, + MeshingParams, +) +from flow360.component.simulation.meshing_param.volume_params import ( + AutomatedFarfield, + AxisymmetricRefinement, + RotationCylinder, + UniformRefinement, +) +from flow360.component.simulation.models.material import Air, SolidMaterial, Sutherland +from flow360.component.simulation.models.solver_numerics import ( + HeatEquationSolver, + KOmegaSST, + KOmegaSSTModelConstants, + LinearSolver, + NavierStokesSolver, + NoneSolver, + SpalartAllmaras, + SpalartAllmarasModelConstants, + TransitionModelSolver, +) +from flow360.component.simulation.models.surface_models import ( + Freestream, + HeatFlux, + Inflow, + Mach, + MassFlowRate, + Outflow, + Periodic, + Pressure, + Rotational, SlipWall, - SolidAdiabaticWall, - SolidIsothermalWall, - SubsonicInflow, - SubsonicOutflowMach, - SubsonicOutflowPressure, - SupersonicInflow, SymmetryPlane, - TranslationallyPeriodic, - VelocityInflow, - WallFunction, + Temperature, + TotalPressure, + Translational, + Wall, ) -from .component.flow360_params.flow360_output import ( - IsoSurfaceOutput, - IsoSurfaces, - MonitorOutput, - Monitors, - ProbeMonitor, - Slice, - SliceOutput, - Slices, - SurfaceIntegralMonitor, - SurfaceOutput, - Surfaces, +from flow360.component.simulation.models.turbulence_quantities import ( + TurbulenceQuantities, ) -from .component.flow360_params.flow360_params import ( +from flow360.component.simulation.models.volume_models import ( ActuatorDisk, - AeroacousticOutput, - AirDensityTemperature, - AirPressureTemperature, + AngleExpression, + AngularVelocity, BETDisk, BETDiskChord, BETDiskSectionalPolar, BETDiskTwist, - Boundaries, - Flow360MeshParams, - Flow360Params, + Fluid, ForcePerArea, - FreestreamFromMach, - FreestreamFromMachReynolds, - FreestreamFromVelocity, - Geometry, - HeatEquationSolver, - MeshBoundary, - PorousMediumBox, - SlidingInterface, - TransitionModelSolver, - UnvalidatedFlow360Params, - UserDefinedDynamic, - VolumeOutput, - VolumeZones, - ZeroFreestream, - ZeroFreestreamFromVelocity, - air, + FromUserDefinedDynamics, + HeatEquationInitialCondition, + NavierStokesInitialCondition, + PorousMedium, + Rotation, + Solid, ) -from .component.flow360_params.initial_condition import ( - ExpressionInitialCondition, - ModifiedRestartSolution, +from flow360.component.simulation.operating_condition.operating_condition import ( + AerospaceCondition, + GenericReferenceCondition, + ThermalState, ) -from .component.flow360_params.solvers import ( - IncompressibleNavierStokesSolver, - KOmegaSST, - KOmegaSSTModelConstants, - LinearSolver, - NavierStokesSolver, - NoneSolver, - PressureCorrectionSolver, - SpalartAllmaras, - SpalartAllmarasModelConstants, +from flow360.component.simulation.outputs.output_entities import ( + Isosurface, + Point, + PointArray, + Slice, ) -from .component.flow360_params.time_stepping import ( +from flow360.component.simulation.outputs.outputs import ( + AeroAcousticOutput, + IsosurfaceOutput, + ProbeOutput, + SliceOutput, + SurfaceIntegralOutput, + SurfaceOutput, + SurfaceProbeOutput, + TimeAverageSliceOutput, + TimeAverageSurfaceOutput, + TimeAverageVolumeOutput, + VolumeOutput, +) +from flow360.component.simulation.primitives import Box, Cylinder, ReferenceGeometry +from flow360.component.simulation.simulation_params import SimulationParams +from flow360.component.simulation.time_stepping.time_stepping import ( AdaptiveCFL, RampCFL, - SteadyTimeStepping, - TimeStepping, - UnsteadyTimeStepping, + Steady, + Unsteady, ) -from .component.flow360_params.turbulence_quantities import TurbulenceQuantities -from .component.flow360_params.volume_zones import ( - FluidDynamicsVolumeZone, - HeatTransferVolumeZone, - InitialConditionHeatTransfer, - PorousMediumVolumeZone, - ReferenceFrame, - ReferenceFrameDynamic, - ReferenceFrameExpression, - ReferenceFrameOmegaDegrees, - ReferenceFrameOmegaRadians, +from flow360.component.simulation.unit_system import ( + SI_unit_system, + imperial_unit_system, ) -from .component.folder import Folder -from .component.meshing.params import ( - Aniso, - BoxRefinement, - CylinderRefinement, - Edges, - Face, - Faces, - Farfield, - ProjectAniso, - RotorDisk, - SurfaceMeshingParams, - UseAdjacent, - Volume, - VolumeMeshingParams, +from flow360.component.simulation.user_defined_dynamics.user_defined_dynamics import ( + UserDefinedDynamic, ) -from .component.surface_mesh import SurfaceMesh -from .component.surface_mesh import SurfaceMeshList as MySurfaceMeshes -from .component.volume_mesh import VolumeMesh -from .component.volume_mesh import VolumeMeshList as MyVolumeMeshes -from .environment import Env -from .flags import Flags -from .user_config import UserConfig -from .version import __solver_version__, __version__ +from flow360.environment import Env +from flow360.version import __solver_version__, __version__ __all__ = [ + "Env", + "__solver_version__", + "__version__", "Accounts", - "ActuatorDisk", + "Project", + "u", + "SimulationParams", + "SI_unit_system", + "imperial_unit_system", + "services", + "MeshingParams", + "MeshingDefaults", + "SurfaceRefinement", + "AutomatedFarfield", + "AxisymmetricRefinement", + "RotationCylinder", + "UniformRefinement", + "SurfaceEdgeRefinement", + "HeightBasedRefinement", + "ReferenceGeometry", + "Cylinder", + "GeometryEntityInfo", + "AerospaceCondition", + "ThermalState", + "Steady", + "Unsteady", + "RampCFL", "AdaptiveCFL", - "AeroacousticOutput", - "AirDensityTemperature", - "AirPressureTemperature", - "Aniso", + "Wall", + "Freestream", + "SlipWall", + "Outflow", + "Inflow", + "Periodic", + "SymmetryPlane", + "Fluid", + "Solid", + "ActuatorDisk", + "AngularVelocity", "BETDisk", "BETDiskChord", "BETDiskSectionalPolar", "BETDiskTwist", - "Boundaries", - "BoxRefinement", - "CGS_unit_system", - "Case", - "CylinderRefinement", - "Edges", - "Env", - "ExpressionInitialCondition", - "Face", - "Faces", - "Farfield", - "Flags", - "Flow360MeshParams", - "Flow360Params", - "FluidDynamicsVolumeZone", - "Folder", - "ForcePerArea", - "FreestreamBoundary", - "FreestreamFromMach", - "FreestreamFromMachReynolds", - "FreestreamFromVelocity", - "Geometry", + "Rotation", + "PorousMedium", + "SurfaceOutput", + "TimeAverageSurfaceOutput", + "VolumeOutput", + "TimeAverageVolumeOutput", + "SliceOutput", + "TimeAverageSliceOutput", + "IsosurfaceOutput", + "SurfaceIntegralOutput", + "ProbeOutput", + "SurfaceProbeOutput", + "AeroAcousticOutput", "HeatEquationSolver", - "HeatFluxWall", - "HeatTransferVolumeZone", - "IncompressibleNavierStokesSolver", - "InitialConditionHeatTransfer", - "IsoSurfaceOutput", - "IsoSurfaces", - "IsothermalWall", - "KOmegaSST", - "KOmegaSSTModelConstants", - "LinearSolver", - "MassInflow", - "MassOutflow", - "MeshBoundary", - "ModifiedRestartSolution", - "MonitorOutput", - "Monitors", - "MyCases", - "MySurfaceMeshes", - "MyVolumeMeshes", "NavierStokesSolver", - "NoSlipWall", "NoneSolver", - "PorousMediumBox", - "PorousMediumVolumeZone", - "PressureCorrectionSolver", - "PressureOutflow", - "ProbeMonitor", - "ProgressCallbackInterface", - "ProjectAniso", - "RampCFL", - "ReferenceFrame", - "ReferenceFrameDynamic", - "ReferenceFrameExpression", - "ReferenceFrameOmegaDegrees", - "ReferenceFrameOmegaRadians", - "RiemannInvariant", - "RotationallyPeriodic", - "RotorDisk", - "SI_unit_system", - "Slice", - "SliceOutput", - "Slices", - "SlidingInterface", - "SlidingInterfaceBoundary", - "SlipWall", - "SolidAdiabaticWall", - "SolidIsothermalWall", "SpalartAllmaras", + "KOmegaSST", "SpalartAllmarasModelConstants", - "SteadyTimeStepping", - "SubsonicInflow", - "SubsonicOutflowMach", - "SubsonicOutflowPressure", - "SupersonicInflow", - "SurfaceIntegralMonitor", - "SurfaceMesh", - "SurfaceMeshingParams", - "SurfaceOutput", - "Surfaces", - "SymmetryPlane", - "TimeStepping", - "TransitionModelSolver", - "TranslationallyPeriodic", + "KOmegaSSTModelConstants", + "LinearSolver", + "ForcePerArea", + "Air", + "Sutherland", + "SolidMaterial", + "Slice", + "Isosurface", "TurbulenceQuantities", - "UnitSystem", - "UnsteadyTimeStepping", - "UnvalidatedFlow360Params", - "UseAdjacent", - "UserConfig", "UserDefinedDynamic", - "VelocityInflow", - "Volume", - "VolumeMesh", - "VolumeMeshingParams", - "VolumeOutput", - "VolumeZones", - "WallFunction", - "ZeroFreestream", - "ZeroFreestreamFromVelocity", - "__version__", - "__solver_version__", - "air", - "flow360", - "flow360_unit_system", - "global_exception_handler", - "imperial_unit_system", - "meshing", - "os", - "pi", - "solvers", - "units", + "Translational", + "NavierStokesInitialCondition", + "FromUserDefinedDynamics", + "HeatEquationInitialCondition", + "Temperature", + "HeatFlux", + "Point", + "PointArray", + "AngleExpression", + "Box", + "GenericReferenceCondition", + "TransitionModelSolver", + "Pressure", + "TotalPressure", + "Rotational", + "Mach", + "MassFlowRate", ] diff --git a/flow360/component/compress_upload.py b/flow360/cloud/compress_upload.py similarity index 98% rename from flow360/component/compress_upload.py rename to flow360/cloud/compress_upload.py index 64548f240..956e96631 100644 --- a/flow360/component/compress_upload.py +++ b/flow360/cloud/compress_upload.py @@ -8,7 +8,7 @@ from flow360.component.resource_base import Flow360Resource -from ..cloud.utils import _get_progress, _S3Action +from .utils import _get_progress, _S3Action # pylint: disable=too-many-arguments, too-many-locals diff --git a/flow360/cloud/requests.py b/flow360/cloud/flow360_requests.py similarity index 70% rename from flow360/cloud/requests.py rename to flow360/cloud/flow360_requests.py index b8e659886..78e143e06 100644 --- a/flow360/cloud/requests.py +++ b/flow360/cloud/flow360_requests.py @@ -7,10 +7,6 @@ from pydantic.alias_generators import to_camel from typing_extensions import Literal -from flow360.flags import Flags - -from ..component.flow360_params.flow360_params import Flow360MeshParams - LengthUnitType = Literal["m", "mm", "cm", "inch", "ft"] @@ -35,45 +31,6 @@ class Config: # pylint: disable=too-few-public-methods allow_population_by_field_name = True -class NewSurfaceMeshRequest(Flow360Requests): - """request for new surface mesh""" - - name: str = pd.Field() - stem: str = pd.Field() - tags: Optional[List[str]] = pd.Field() - geometry_id: Optional[str] = pd.Field(alias="geometryId") - config: Optional[str] = pd.Field() - mesh_format: Optional[Literal["aflr3", "cgns", "stl"]] = pd.Field(alias="meshFormat") - endianness: Optional[Literal["little", "big"]] = pd.Field(alias="meshEndianness") - compression: Optional[Literal["gz", "bz2", "zst"]] = pd.Field(alias="meshCompression") - solver_version: Optional[str] = pd.Field(alias="solverVersion") - if Flags.beta_features(): - version: Optional[Literal["v1", "v2"]] = pd.Field(default="v1") - - -class NewVolumeMeshRequest(Flow360Requests): - """request for new volume mesh""" - - name: str = pd.Field(alias="meshName") - file_name: str = pd.Field(alias="fileName") - tags: Optional[List[str]] = pd.Field(alias="meshTags") - format: Literal["aflr3", "cgns"] = pd.Field(alias="meshFormat") - endianness: Optional[Literal["little", "big"]] = pd.Field(alias="meshEndianness") - compression: Optional[Literal["gz", "bz2", "zst"]] = pd.Field(alias="meshCompression") - mesh_params: Optional[Flow360MeshParams] = pd.Field(alias="meshParams") - solver_version: Optional[str] = pd.Field(alias="solverVersion") - if Flags.beta_features(): - version: Optional[Literal["v1", "v2"]] = pd.Field(alias="version", default="v1") - - # pylint: disable=no-self-argument - @pd.validator("mesh_params") - def set_mesh_params(cls, value: Union[Flow360MeshParams, None]): - """validate mesh params""" - if value: - return value.flow360_json() - return value - - class CopyExampleVolumeMeshRequest(Flow360Requests): """request for new volume mesh""" diff --git a/flow360/component/case.py b/flow360/component/case.py index 33fc2bab3..e3c6d0bc7 100644 --- a/flow360/component/case.py +++ b/flow360/component/case.py @@ -13,12 +13,11 @@ import pydantic.v1 as pd_v1 from .. import error_messages -from ..cloud.requests import MoveCaseItem, MoveToFolderRequest +from ..cloud.flow360_requests import MoveCaseItem, MoveToFolderRequest from ..cloud.rest_api import RestApi from ..cloud.s3_utils import CloudFileNotFoundError from ..exceptions import Flow360RuntimeError, Flow360ValidationError, Flow360ValueError from ..log import log -from .flow360_params.flow360_params import Flow360Params, UnvalidatedFlow360Params from .folder import Folder from .interfaces import CaseInterface, FolderInterface, VolumeMeshInterface from .resource_base import ( @@ -58,6 +57,7 @@ shared_account_confirm_proceed, validate_type, ) +from .v1.flow360_params import Flow360Params, UnvalidatedFlow360Params from .validator import Validator diff --git a/flow360/component/folder.py b/flow360/component/folder.py index 80619bfcc..1f747a6e7 100644 --- a/flow360/component/folder.py +++ b/flow360/component/folder.py @@ -8,7 +8,11 @@ import pydantic.v1 as pd -from ..cloud.requests import MoveFolderItem, MoveToFolderRequest, NewFolderRequest +from ..cloud.flow360_requests import ( + MoveFolderItem, + MoveToFolderRequest, + NewFolderRequest, +) from ..cloud.rest_api import RestApi from ..exceptions import Flow360ValueError from ..log import log diff --git a/flow360/component/geometry.py b/flow360/component/geometry.py index 37c2760d1..e79ddc41f 100644 --- a/flow360/component/geometry.py +++ b/flow360/component/geometry.py @@ -11,8 +11,12 @@ import pydantic as pd +from flow360.cloud.flow360_requests import ( + GeometryFileMeta, + LengthUnitType, + NewGeometryRequest, +) from flow360.cloud.heartbeat import post_upload_heartbeat -from flow360.cloud.requests import GeometryFileMeta, LengthUnitType, NewGeometryRequest from flow360.cloud.rest_api import RestApi from flow360.component.interfaces import GeometryInterface from flow360.component.resource_base import ( diff --git a/flow360/component/project.py b/flow360/component/project.py index 1f4e1a202..cc9c2912f 100644 --- a/flow360/component/project.py +++ b/flow360/component/project.py @@ -9,9 +9,9 @@ import pydantic as pd -from flow360 import Case, SurfaceMesh, __solver_version__ -from flow360.cloud.requests import LengthUnitType +from flow360.cloud.flow360_requests import LengthUnitType from flow360.cloud.rest_api import RestApi +from flow360.component.case import Case from flow360.component.geometry import Geometry from flow360.component.interfaces import ( GeometryInterface, @@ -26,6 +26,7 @@ from flow360.component.simulation.utils import model_attribute_unlock from flow360.component.simulation.web.asset_base import AssetBase from flow360.component.simulation.web.draft import Draft +from flow360.component.surface_mesh import SurfaceMesh from flow360.component.utils import ( SUPPORTED_GEOMETRY_FILE_PATTERNS, MeshNameParser, @@ -34,6 +35,7 @@ ) from flow360.component.volume_mesh import VolumeMeshV2 from flow360.exceptions import Flow360FileError, Flow360ValueError, Flow360WebError +from flow360.version import __solver_version__ AssetOrResource = Union[type[AssetBase], type[Flow360Resource]] RootAsset = Union[Geometry, VolumeMeshV2] @@ -55,7 +57,7 @@ class RootType(Enum): VOLUME_MESH = "VolumeMesh" -class ProjectMeta(pd.BaseModel, extra=pd.Extra.allow): +class ProjectMeta(pd.BaseModel, extra="allow"): """ Metadata class for a project. diff --git a/flow360/component/results/case_results.py b/flow360/component/results/case_results.py index 4b3135370..f6f9a511a 100644 --- a/flow360/component/results/case_results.py +++ b/flow360/component/results/case_results.py @@ -27,10 +27,10 @@ ) from ...exceptions import Flow360ValueError from ...log import log -from ..flow360_params.conversions import unit_converter as unit_converter_v1 -from ..flow360_params.flow360_params import Flow360Params from ..simulation.conversion import unit_converter as unit_converter_v2 from ..simulation.simulation_params import SimulationParams +from ..v1.conversions import unit_converter as unit_converter_v1 +from ..v1.flow360_params import Flow360Params # pylint: disable=consider-using-with TMP_DIR = tempfile.TemporaryDirectory() diff --git a/flow360/component/simulation/conversion.py b/flow360/component/simulation/conversion.py index 79318a05c..448424843 100644 --- a/flow360/component/simulation/conversion.py +++ b/flow360/component/simulation/conversion.py @@ -118,7 +118,7 @@ def unit_converter(dimension, mesh_unit: u.unyt_quantity, params, required_by: L ------- flow360_conversion_unit_system The conversion unit system for the specified dimension. This unit system allows for - .in_base(unit_system="flow360") conversion. + .in_base(unit_system="flow360_v2") conversion. Raises ------ diff --git a/flow360/component/simulation/framework/base_model.py b/flow360/component/simulation/framework/base_model.py index b3f84bf35..f869fe6ef 100644 --- a/flow360/component/simulation/framework/base_model.py +++ b/flow360/component/simulation/framework/base_model.py @@ -676,7 +676,7 @@ def _convert_dimensions_to_solver( ) # pylint: disable=no-member value.units.registry = flow360_conv_system.registry - solver_values[property_name] = value.in_base(unit_system="flow360") + solver_values[property_name] = value.in_base(unit_system="flow360_v2") log.debug(f" converted to: {solver_values[property_name]}") elif isinstance(value, list) and property_name not in exclude: new_value = [] @@ -690,7 +690,7 @@ def _convert_dimensions_to_solver( ) # pylint: disable=no-member item.units.registry = flow360_conv_system.registry - new_value.append(item.in_base(unit_system="flow360")) + new_value.append(item.in_base(unit_system="flow360_v2")) else: new_value.append(item) solver_values[property_name] = new_value @@ -759,6 +759,6 @@ def preprocess( exclude=exclude, ) elif isinstance(item, unyt_quantity): - solver_values[property_name][i] = item.in_base(unit_system="flow360") + solver_values[property_name][i] = item.in_base(unit_system="flow360_v2") return self.__class__(**solver_values) diff --git a/flow360/component/simulation/meshing_param/edge_params.py b/flow360/component/simulation/meshing_param/edge_params.py index 6bc2b76d0..5308754c8 100644 --- a/flow360/component/simulation/meshing_param/edge_params.py +++ b/flow360/component/simulation/meshing_param/edge_params.py @@ -11,14 +11,14 @@ class AngleBasedRefinement(Flow360BaseModel): - """Surface edge refinement by specifying curvature resolution in degrees""" + """Surface edge refinement by specifying curvature resolution angle.""" type: Literal["angle"] = pd.Field("angle", frozen=True) value: AngleType = pd.Field() class HeightBasedRefinement(Flow360BaseModel): - """Surface edge refinement by specifying first layer height of the anisotropic layers""" + """Surface edge refinement by specifying first layer height of the anisotropic layers.""" type: Literal["height"] = pd.Field("height", frozen=True) # pylint: disable=no-member @@ -26,24 +26,21 @@ class HeightBasedRefinement(Flow360BaseModel): class AspectRatioBasedRefinement(Flow360BaseModel): - """Surface edge refinement by specifying maximum aspect ratio of the anisotropic cells""" + """Surface edge refinement by specifying maximum aspect ratio of the anisotropic cells.""" type: Literal["aspectRatio"] = pd.Field("aspectRatio", frozen=True) value: pd.PositiveFloat = pd.Field() class ProjectAnisoSpacing(Flow360BaseModel): - """Project the anisotropic spacing from neighboring faces to the edge""" + """Project the anisotropic spacing from neighboring faces to the edge.""" type: Literal["projectAnisoSpacing"] = pd.Field("projectAnisoSpacing", frozen=True) class SurfaceEdgeRefinement(Flow360BaseModel): """ - Grow anisotropic layers orthogonal to the edge. - - If `method` is None then it projects the anisotropic spacing from neighboring faces to the edge - (equivalent to `ProjectAniso` in old params). + Setting for growing anisotropic layers orthogonal to the specified `Edge`s. """ name: Optional[str] = pd.Field(None) @@ -56,4 +53,8 @@ class SurfaceEdgeRefinement(Flow360BaseModel): HeightBasedRefinement, AspectRatioBasedRefinement, ProjectAnisoSpacing, - ] = pd.Field(discriminator="type") + ] = pd.Field( + discriminator="type", + description="Method for determining the spacing. See :class:`AngleBasedRefinement`," + " :class:`HeightBasedRefinement`, :class:`AspectRatioBasedRefinement`, :class:`ProjectAnisoSpacing`", + ) diff --git a/flow360/component/simulation/meshing_param/face_params.py b/flow360/component/simulation/meshing_param/face_params.py index 97f53cd46..f5a8e7ae3 100644 --- a/flow360/component/simulation/meshing_param/face_params.py +++ b/flow360/component/simulation/meshing_param/face_params.py @@ -12,15 +12,7 @@ class SurfaceRefinement(Flow360BaseModel): """ - These affects surface meshing. - - Note: - - `None` entities will be expanded (or just ignored and convert to global default, depending on implementation) - before submission. This is supposed to be applied to all the matching entities. We allow this so that we do not - need to have dedicated field for global settings. This is also consistent with the `FluidDynamics` class' design. - - - For `SurfaceRefinement` we may need validation to detect if default has been set or not. This is because we need - these defaults so that the when face name is not present, what config we ues. Depending on how we go down the road. + Setting for refining surface elements for given `Surface`. """ name: Optional[str] = pd.Field(None) @@ -28,25 +20,33 @@ class SurfaceRefinement(Flow360BaseModel): entities: EntityList[Surface] = pd.Field(alias="faces") # pylint: disable=no-member max_edge_length: LengthType.Positive = pd.Field( - description="Local maximum edge length for surface cells." + description="Maximum edge length of surface cells." ) class PassiveSpacing(Flow360BaseModel): """ - Passively control the mesh spacing either through other face's meshing + Passively control the mesh spacing either through adjecent `Surface`'s meshing setting or doing nothing to change existing surface mesh at all. """ name: Optional[str] = pd.Field(None) - type: Literal["projected", "unchanged"] = pd.Field() + type: Literal["projected", "unchanged"] = pd.Field( + description=""" + 1. When set to *projected*, turn off anisotropic layers growing for this `Surface`. + Project the anisotropic spacing from the neighboring volumes to this face. + + 2. When set to *unchanged*, turn off anisotropic layers growing for this `Surface`. + The surface mesh will remain unaltered when populating the volume mesh. + """ + ) refinement_type: Literal["PassiveSpacing"] = pd.Field("PassiveSpacing", frozen=True) entities: EntityList[Surface] = pd.Field(alias="faces") class BoundaryLayer(Flow360BaseModel): """ - These affects volume meshing. + Setting for growing anisotropic layers orthogonal to the specified `Surface`s. """ name: Optional[str] = pd.Field(None) @@ -54,5 +54,5 @@ class BoundaryLayer(Flow360BaseModel): entities: EntityList[Surface] = pd.Field(alias="faces") # pylint: disable=no-member first_layer_thickness: LengthType.Positive = pd.Field( - description="First layer thickness for volumetric anisotropic layers grown from given faces." + description="First layer thickness for volumetric anisotropic layers grown from given `Surface`s." ) diff --git a/flow360/component/simulation/meshing_param/params.py b/flow360/component/simulation/meshing_param/params.py index d47f7f522..73edc7cb7 100644 --- a/flow360/component/simulation/meshing_param/params.py +++ b/flow360/component/simulation/meshing_param/params.py @@ -54,75 +54,78 @@ class MeshingDefaults(Flow360BaseModel): surface_edge_growth_rate: float = ContextField( 1.2, ge=1, - description="Global growth rate of the anisotropic layers grown from the edges.", + description="Growth rate of the anisotropic layers grown from the edges." + "This can not be overridden per edge.", context=SURFACE_MESH, ) ##:: Default boundary layer settings boundary_layer_growth_rate: float = ContextField( 1.2, - description="Default growth rate for volume prism layers.", + description="Default growth rate for volume prism layers." + " This can not be overridden per face.", ge=1, context=VOLUME_MESH, ) # pylint: disable=no-member boundary_layer_first_layer_thickness: Optional[LengthType.Positive] = ConditionalField( None, - description="Default first layer thickness for volumetric anisotropic layers.", + description="Default first layer thickness for volumetric anisotropic layers." + " This can be overridden with :class:`~flow360.BoundaryLayer`.", context=VOLUME_MESH, ) # Truly optional if all BL faces already have first_layer_thickness ##:: Default surface layer settings surface_max_edge_length: Optional[LengthType.Positive] = ConditionalField( None, - description="Default maximum edge length for surface cells.", + description="Default maximum edge length for surface cells." + " This can be overridden with :class:`~flow360.SurfaceRefinement`.", context=SURFACE_MESH, ) curvature_resolution_angle: AngleType.Positive = ContextField( 12 * u.deg, - description="Default maximum angular deviation in degrees. This value will restrict:" - "(1) The angle between a cell’s normal and its underlying surface normal" - "(2) The angle between a line segment’s normal and its underlying curve normal" - "This can not be overridden per face.", + description=( + "Default maximum angular deviation in degrees. This value will restrict:" + " 1. The angle between a cell’s normal and its underlying surface normal." + " 2. The angle between a line segment’s normal and its underlying curve normal." + " This can not be overridden per face." + ), context=SURFACE_MESH, ) class MeshingParams(Flow360BaseModel): """ - Meshing parameters for volume and/or surface mesher. - - In `Simulation` this only contains what the user specifies. `Simulation` can derive and add more items according - to other aspects of simulation. (E.g. BETDisk volume -> ZoneRefinement) - - Meshing related but may and maynot (user specified) need info from `Simulation`: - 1. Add rotational zones. - 2. Add default BETDisk refinement. + Meshing parameters for volume and/or surface mesher. This contains all the meshing related settings. """ refinement_factor: Optional[pd.PositiveFloat] = pd.Field( default=1, - description="If refinementFactor=r is provided all spacings in refinementregions" - + "and first layer thickness will be adjusted to generate r-times finer mesh.", + description="All spacings in refinement regions" + + "and first layer thickness will be adjusted to generate `r`-times" + + " finer mesh where r is the refinement_factor value.", ) gap_treatment_strength: Optional[float] = ContextField( default=0, ge=0, le=1, description="Narrow gap treatment strength used when two surfaces are in close proximity." - "Use a value between 0 and 1, where 0 is no treatment and 1 is the most conservative treatment." - + "This parameter has a global impact where the anisotropic transition into the isotropic mesh." - + "However the impact on regions without close proximity is negligible.", + " Use a value between 0 and 1, where 0 is no treatment and 1 is the most conservative treatment." + " This parameter has a global impact where the anisotropic transition into the isotropic mesh." + " However the impact on regions without close proximity is negligible.", context=VOLUME_MESH, ) defaults: MeshingDefaults = pd.Field( - MeshingDefaults(), description="Default settings for meshing." + MeshingDefaults(), + description="Default settings for meshing." + " In other words the settings specified here will be applied" + " as a default setting for all `Surface` and `Edges`.", ) refinements: List[RefinementTypes] = pd.Field( default=[], - description="Additional fine-tunning for refinements.", + description="Additional fine-tunning for refinements on top of :paramref:`defaults`", ) # Will add more to the Union volume_zones: Optional[List[VolumeZonesTypes]] = pd.Field( diff --git a/flow360/component/simulation/meshing_param/volume_params.py b/flow360/component/simulation/meshing_param/volume_params.py index 62da95473..f04455c3e 100644 --- a/flow360/component/simulation/meshing_param/volume_params.py +++ b/flow360/component/simulation/meshing_param/volume_params.py @@ -20,33 +20,38 @@ class UniformRefinement(Flow360BaseModel): - """Uniform spacing refinement.""" + """Uniform spacing refinement inside specified region of mesh.""" name: Optional[str] = pd.Field(None) refinement_type: Literal["UniformRefinement"] = pd.Field("UniformRefinement", frozen=True) - entities: EntityList[Box, Cylinder] = pd.Field() + entities: EntityList[Box, Cylinder] = pd.Field( + description=":class:`UniformRefinement` can be applied to `Box` and `Cylinder` regions." + ) # pylint: disable=no-member - spacing: LengthType.Positive = pd.Field() + spacing: LengthType.Positive = pd.Field(description="The required refinement spacing.") class CylindricalRefinementBase(Flow360BaseModel, metaclass=ABCMeta): """Base class for all refinements that requires spacing in axia, radial and circumferential directions.""" # pylint: disable=no-member - spacing_axial: LengthType.Positive = pd.Field() - spacing_radial: LengthType.Positive = pd.Field() - spacing_circumferential: LengthType.Positive = pd.Field() + spacing_axial: LengthType.Positive = pd.Field(description="Spacing along the axial direction.") + spacing_radial: LengthType.Positive = pd.Field( + description="Spacing along the radial direction." + ) + spacing_circumferential: LengthType.Positive = pd.Field( + description="Spacing along the circumferential direction." + ) class AxisymmetricRefinement(CylindricalRefinementBase): """ - Note: - - This basically creates the "rotorDisks" type of volume refinement that we used to have. - - - - - We may provide a helper function to automatically determine what is inside the encloeud_objects list based on - the mesh data. But this currently is out of scope due to the estimated efforts. + - The mesh inside the :class:`AxisymmetricRefinement` is semi-structured. + - The :class:`AxisymmetricRefinement` cannot enclose/intersect with other objects. + - Users could create a donut-shape :class:`AxisymmetricRefinement` and place their hub/centerbody in the middle. + - :class:`AxisymmetricRefinement` can be used for resolving the strong flow gradient + along the axial direction for the actuator or BET disks. + - The spacings along the axial, radial and circumferential directions can be adjusted independently. """ name: Optional[str] = pd.Field(None) @@ -58,25 +63,23 @@ class AxisymmetricRefinement(CylindricalRefinementBase): class RotationCylinder(CylindricalRefinementBase): """ - This is the original SlidingInterface. This will create new volume zones - Will add RotationSphere class in the future. - Please refer to - https://www.notion.so/flexcompute/Python-model-design-document- - 78d442233fa944e6af8eed4de9541bb1?pvs=4#c2de0b822b844a12aa2c00349d1f68a3 - - - `enclosed_entities` is actually just a way of specifying the enclosing patches of a volume zone. - Therefore in the future when supporting arbitrary-axisymmetric shaped sliding interface, we may not need this - attribute at all. For example if the new class already has an entry to list all the enclosing patches. + - The mesh on :class:`RotationCylinder` is guaranteed to be concentric. + - The :class:`RotationCylinder` is designed to enclose other objects, but it can’t intersect with other objects. + - Users could create a donut-shape :class:`RotationCylinder` and put their stationary centerbody in the middle. + This type of volume zone can be used to generate volume zone compatible with :class:`~flow360.Rotation` model. """ + # Note: Please refer to + # Note: https://www.notion.so/flexcompute/Python-model-design-document- + # Note: 78d442233fa944e6af8eed4de9541bb1?pvs=4#c2de0b822b844a12aa2c00349d1f68a3 + type: Literal["RotationCylinder"] = pd.Field("RotationCylinder", frozen=True) name: Optional[str] = pd.Field(None, description="Name to display in the GUI.") entities: EntityList[Cylinder] = pd.Field() enclosed_entities: Optional[EntityList[Cylinder, Surface]] = pd.Field( None, - description="Entities enclosed by this sliding interface." - + " Can be faces, boxes and/or other cylinders etc." - + "This helps determining the volume zone boundary.", + description="Entities enclosed by :class:`RotationCylinder`." + " Can be `Surface`s and/or other `Cylinders`.", ) @pd.field_validator("entities", mode="after") @@ -98,24 +101,23 @@ def _validate_single_instance_in_entity_list(cls, values): class AutomatedFarfield(Flow360BaseModel): """ - - auto: The mesher will Sphere or semi-sphere will be generated based on the bounding box of the geometry - - - Full sphere if min{Y} < 0 and max{Y} > 0 - - - +Y semi sphere if min{Y} = 0 and max{Y} > 0 - - - -Y semi sphere if min{Y} < 0 and max{Y} = 0 - - - quasi-3d: Thin disk will be generated for quasi 3D cases. - Both sides of the farfield disk will be treated as “symmetric plane”. - - - user-defined: The farfield shape is provided by the user in ESP. - Note: "user-defined" are left out due to scarce usage and will not be implemented. + Settings for automatic farfield volume zone generation. """ type: Literal["AutomatedFarfield"] = pd.Field("AutomatedFarfield", frozen=True) name: Optional[str] = pd.Field(None) - method: Literal["auto", "quasi-3d"] = pd.Field(default="auto", frozen=True) + method: Literal["auto", "quasi-3d"] = pd.Field( + default="auto", + frozen=True, + description=""" + - auto: The mesher will Sphere or semi-sphere will be generated based on the bounding box of the geometry. + - Full sphere if min{Y} < 0 and max{Y} > 0. + - +Y semi sphere if min{Y} = 0 and max{Y} > 0. + - -Y semi sphere if min{Y} < 0 and max{Y} = 0. + - quasi-3d: Thin disk will be generated for quasi 3D cases. + Both sides of the farfield disk will be treated as “symmetric plane”. + """, + ) private_attribute_entity: GenericVolume = pd.Field( GenericVolume(name="__farfield_zone_name_not_properly_set_yet"), frozen=True, exclude=True ) diff --git a/flow360/component/simulation/models/material.py b/flow360/component/simulation/models/material.py index 59537f72f..4757baec8 100644 --- a/flow360/component/simulation/models/material.py +++ b/flow360/component/simulation/models/material.py @@ -30,19 +30,40 @@ class MaterialBase(Flow360BaseModel): class Sutherland(Flow360BaseModel): """ - Sutherland's law + Represents Sutherland's law for calculating dynamic viscosity. + + This class implements Sutherland's formula to compute the dynamic viscosity of a gas + as a function of temperature. """ # pylint: disable=no-member - reference_viscosity: ViscosityType.NonNegative = pd.Field() - reference_temperature: TemperatureType.Positive = pd.Field() - effective_temperature: TemperatureType.Positive = pd.Field() + reference_viscosity: ViscosityType.NonNegative = pd.Field( + description="The reference dynamic viscosity at the reference temperature." + ) + reference_temperature: TemperatureType.Positive = pd.Field( + description="The reference temperature associated with the reference viscosity." + ) + effective_temperature: TemperatureType.Positive = pd.Field( + description="The effective temperature constant used in Sutherland's formula." + ) @pd.validate_call def get_dynamic_viscosity( self, temperature: TemperatureType.Positive ) -> ViscosityType.NonNegative: - """dynamic viscosity""" + """ + Calculates the dynamic viscosity at a given temperature using Sutherland's law. + + Parameters + ---------- + temperature : TemperatureType.Positive + The temperature at which to calculate the dynamic viscosity. + + Returns + ------- + ViscosityType.NonNegative + The calculated dynamic viscosity at the specified temperature. + """ return self.reference_viscosity * float( pow(temperature / self.reference_temperature, 1.5) * (self.reference_temperature + self.effective_temperature) @@ -53,7 +74,9 @@ def get_dynamic_viscosity( # pylint: disable=no-member, missing-function-docstring class Air(MaterialBase): """ - Material properties for Air + Represents the material properties for air. + This sets specific material properties for air, + including dynamic viscosity, specific heat ratio, gas constant, and Prandtl number. """ type: Literal["air"] = pd.Field("air", frozen=True) @@ -65,35 +88,106 @@ class Air(MaterialBase): # pylint: disable=fixme # TODO: validation error for effective_temperature not equal 110.4 K effective_temperature=110.4 * u.K, - ) + ), + description=( + "The dynamic viscosity model or value for air. Defaults to a `Sutherland` " + "model with standard atmospheric conditions." + ), ) @property def specific_heat_ratio(self) -> pd.PositiveFloat: + """ + Returns the specific heat ratio (gamma) for air. + + Returns + ------- + pd.PositiveFloat + The specific heat ratio, typically 1.4 for air. + """ return 1.4 @property def gas_constant(self) -> SpecificHeatCapacityType.Positive: + """ + Returns the specific gas constant for air. + + Returns + ------- + SpecificHeatCapacityType.Positive + The specific gas constant for air. + """ + return 287.0529 * u.m**2 / u.s**2 / u.K @property def prandtl_number(self) -> pd.PositiveFloat: + """ + Returns the Prandtl number for air. + + Returns + ------- + pd.PositiveFloat + The Prandtl number, typically around 0.72 for air. + """ + return 0.72 @pd.validate_call def get_pressure( self, density: DensityType.Positive, temperature: TemperatureType.Positive ) -> PressureType.Positive: + """ + Calculates the pressure of air using the ideal gas law. + + Parameters + ---------- + density : DensityType.Positive + The density of the air. + temperature : TemperatureType.Positive + The temperature of the air. + + Returns + ------- + PressureType.Positive + The calculated pressure. + """ return density * self.gas_constant * temperature @pd.validate_call def get_speed_of_sound(self, temperature: TemperatureType.Positive) -> VelocityType.Positive: + """ + Calculates the speed of sound in air at a given temperature. + + Parameters + ---------- + temperature : TemperatureType.Positive + The temperature at which to calculate the speed of sound. + + Returns + ------- + VelocityType.Positive + The speed of sound at the specified temperature. + """ return sqrt(self.specific_heat_ratio * self.gas_constant * temperature) @pd.validate_call def get_dynamic_viscosity( self, temperature: TemperatureType.Positive ) -> ViscosityType.NonNegative: + """ + Calculates the dynamic viscosity of air at a given temperature. + + Parameters + ---------- + temperature : TemperatureType.Positive + The temperature at which to calculate the dynamic viscosity. + + Returns + ------- + ViscosityType.NonNegative + The dynamic viscosity at the specified temperature. + """ if isinstance(self.dynamic_viscosity, Sutherland): return self.dynamic_viscosity.get_dynamic_viscosity(temperature) return self.dynamic_viscosity diff --git a/flow360/component/simulation/models/solver_numerics.py b/flow360/component/simulation/models/solver_numerics.py index ed2ca61bb..cc55b066b 100644 --- a/flow360/component/simulation/models/solver_numerics.py +++ b/flow360/component/simulation/models/solver_numerics.py @@ -31,42 +31,29 @@ class LinearSolver(Flow360BaseModel): - """:class:`LinearSolver` class for setting up linear solver for heat equation - - - Parameters - ---------- - - max_iterations : PositiveInt, optional - Maximum number of linear solver iterations, by default 50 - - absolute_tolerance : PositiveFloat, optional - The linear solver converges when the final residual of the pseudo steps below this value. Either absolute - tolerance or relative tolerance can be used to determine convergence, by default 1e-10 - - relative_tolerance : - The linear solver converges when the ratio of the final residual and the initial - residual of the pseudo step is below this value. - - validation: tolerance settings only available to HeatEquationSolver - - Returns - ------- - :class:`LinearSolver` - An instance of the component class LinearSolver. - + """:class:`LinearSolver` class for setting up the linear solver. Example ------- >>> ls = LinearSolver( - max_iterations=50, - absoluteTolerance=1e-10 - ) + ... max_iterations=50, + ... absoluteTolerance=1e-10 + ... ) """ - max_iterations: PositiveInt = pd.Field(30) - absolute_tolerance: Optional[PositiveFloat] = pd.Field(None) - relative_tolerance: Optional[PositiveFloat] = pd.Field(None) + max_iterations: PositiveInt = pd.Field( + 30, description="Maximum number of linear solver iterations." + ) + absolute_tolerance: Optional[PositiveFloat] = pd.Field( + None, + description="The linear solver converges when the final residual of the pseudo steps below this value." + + "Either absolute tolerance or relative tolerance can be used to determine convergence.", + ) + relative_tolerance: Optional[PositiveFloat] = pd.Field( + None, + description="The linear solver converges when the ratio of the final residual and the initial " + + "residual of the pseudo step is below this value.", + ) model_config = pd.ConfigDict( conflicting_fields=[Conflicts(field1="absolute_tolerance", field2="relative_tolerance")] @@ -77,98 +64,95 @@ class GenericSolverSettings(Flow360BaseModel, metaclass=ABCMeta): """:class:`GenericSolverSettings` class""" absolute_tolerance: PositiveFloat = pd.Field(1.0e-10) - relative_tolerance: NonNegativeFloat = pd.Field(0) - order_of_accuracy: Literal[1, 2] = pd.Field(2) - equation_evaluation_frequency: PositiveInt = pd.Field(1) + relative_tolerance: NonNegativeFloat = pd.Field( + 0, + description="Tolerance to the relative residual, below which the solver goes to the next physical step. " + + "Relative residual is defined as the ratio of the current pseudoStep's residual to the maximum " + + "residual present in the first 10 pseudoSteps within the current physicalStep. " + + "NOTE: relativeTolerance is ignored in steady simulations and only absoluteTolerance is " + + "used as the convergence criterion.", + ) + order_of_accuracy: Literal[1, 2] = pd.Field(2, description="Order of accuracy in space.") + equation_evaluation_frequency: PositiveInt = pd.Field( + 1, description="Frequency at which to solve the equation." + ) linear_solver: LinearSolver = pd.Field(LinearSolver()) class NavierStokesSolver(GenericSolverSettings): - """:class:`NavierStokesSolver` class for setting up compressible Navier-Stokes solver - - Parameters - ---------- - - absolute_tolerance : - Tolerance for the NS residual, below which the solver goes to the next physical step - - relative_tolerance : - Tolerance to the relative residual, below which the solver goes to the next physical step. Relative residual is - defined as the ratio of the current pseudoStep’s residual to the maximum residual present in the first - 10 pseudoSteps within the current physicalStep. NOTE: relativeTolerance is ignored in steady simulations and - only absoluteTolerance is used as the convergence criterion - - CFL_multiplier : - Factor to the CFL definitions defined in “timeStepping” section - - kappa_MUSCL : - Kappa for the MUSCL scheme, range from [-1, 1], with 1 being unstable. The default value of -1 leads to a 2nd - order upwind scheme and is the most stable. A value of 0.33 leads to a blended upwind/central scheme and is - recommended for low subsonic flows leading to reduced dissipation - - update_jacobian_frequency : - Frequency at which the jacobian is updated. - - equation_evaluation_frequency : - Frequency at which to update the compressible NS equation in loosely-coupled simulations - - max_force_jac_update_physical_steps : - When which physical steps, the jacobian matrix is updated every pseudo step - - order_of_accuracy : - Order of accuracy in space - - limit_velocity : - Limiter for velocity - - limit_pressure_density : - Limiter for pressure and density - - numerical_dissipation_factor : - A factor in the range [0.01, 1.0] which exponentially reduces the dissipation of the numerical flux. - The recommended starting value for most low-dissipation runs is 0.2 - - linear_solver: - Linear solver settings - - low_mach_preconditioner: - Uses preconditioning for accelerating low Mach number flows. - - low_mach_preconditioner_threshold: - For flow regions with Mach numbers smaller than threshold, the input Mach number to the preconditioner is - assumed to be the threshold value if it is smaller than the threshold. - The default value for the threshold is the freestream Mach number. - - Returns - ------- - :class:`NavierStokesSolver` - An instance of the component class NavierStokesSolver. + """:class:`NavierStokesSolver` class for setting up the compressible Navier-Stokes solver. + For more information on setting up the numerical parameters for the Navier-Stokes solver, + refer to :ref:`Navier-Stokes solver knowledge base `. Example ------- - >>> ns = NavierStokesSolver(absolute_tolerance=1e-10) + >>> ns = navier_stokes_solver=NavierStokesSolver(absolute_tolerance=1e-10, + ... numerical_dissipation_factor=0.01, + ... linear_solver=LinearSolver(max_iterations=50), + ... low_mach_preconditioner=True, + ... ) """ - absolute_tolerance: PositiveFloat = pd.Field(1.0e-10) + absolute_tolerance: PositiveFloat = pd.Field( + 1.0e-10, + description="Tolerance for the NS residual, below which the solver goes to the next physical step.", + ) - CFL_multiplier: PositiveFloat = pd.Field(1.0) - kappa_MUSCL: pd.confloat(ge=-1, le=1) = pd.Field(-1) + CFL_multiplier: PositiveFloat = pd.Field( + 1.0, + description="Factor to the CFL definitions defined in the " + + ":ref:`Time Stepping ` section.", + ) + kappa_MUSCL: pd.confloat(ge=-1, le=1) = pd.Field( + -1, + description="Kappa for the MUSCL scheme, range from [-1, 1], with 1 being unstable. " + + "The default value of -1 leads to a 2nd order upwind scheme and is the most stable. " + + "A value of 0.33 leads to a blended upwind/central scheme and is recommended for low " + + "subsonic flows leading to reduced dissipation.", + ) - numerical_dissipation_factor: pd.confloat(ge=0.01, le=1) = pd.Field(1) - limit_velocity: bool = pd.Field(False) - limit_pressure_density: bool = pd.Field(False) + numerical_dissipation_factor: pd.confloat(ge=0.01, le=1) = pd.Field( + 1, + description="A factor in the range [0.01, 1.0] which exponentially reduces the " + + "dissipation of the numerical flux. The recommended starting value for most " + + "low-dissipation runs is 0.2.", + ) + limit_velocity: bool = pd.Field(False, description="Limiter for velocity") + limit_pressure_density: bool = pd.Field(False, description="Limiter for pressure and density.") type_name: Literal["Compressible"] = pd.Field("Compressible", frozen=True) - low_mach_preconditioner: bool = pd.Field(False) - low_mach_preconditioner_threshold: Optional[NonNegativeFloat] = pd.Field(None) + low_mach_preconditioner: bool = pd.Field( + False, description="Use preconditioning for accelerating low Mach number flows." + ) + low_mach_preconditioner_threshold: Optional[NonNegativeFloat] = pd.Field( + None, + description="For flow regions with Mach numbers smaller than threshold, the input " + + "Mach number to the preconditioner is assumed to be the threshold value if it is " + + "smaller than the threshold. The default value for the threshold is the freestream " + + "Mach number.", + ) - update_jacobian_frequency: PositiveInt = pd.Field(4) - max_force_jac_update_physical_steps: NonNegativeInt = pd.Field(0) + update_jacobian_frequency: PositiveInt = pd.Field( + 4, description="Frequency at which the jacobian is updated." + ) + max_force_jac_update_physical_steps: NonNegativeInt = pd.Field( + 0, + description="When physical step is less than this value, the jacobian matrix is " + + "updated every pseudo step.", + ) class SpalartAllmarasModelConstants(Flow360BaseModel): - """:class:`SpalartAllmarasModelConstants` class""" + """ + :class:`SpalartAllmarasModelConstants` class specifies the constants of the Spalart-Allmaras model. + + Example + ------- + >>> ts = SpalartAllmaras( + ... modeling_constants = SpalartAllmarasModelConstants(C_w2=2.718) + ... ) + """ type_name: Literal["SpalartAllmarasConsts"] = pd.Field("SpalartAllmarasConsts", frozen=True) C_DES: NonNegativeFloat = pd.Field(0.72) @@ -185,7 +169,15 @@ class SpalartAllmarasModelConstants(Flow360BaseModel): class KOmegaSSTModelConstants(Flow360BaseModel): - """:class:`KOmegaSSTModelConstants` class""" + """ + :class:`KOmegaSSTModelConstants` class specifies the constants of the SST k-omega model. + + Example + ------- + >>> ts = SpalartAllmaras( + ... modeling_constants = KOmegaSSTModelConstants(C_sigma_omega1=2.718) + ... ) + """ type_name: Literal["kOmegaSSTConsts"] = pd.Field("kOmegaSSTConsts", frozen=True) C_DES1: NonNegativeFloat = pd.Field(0.78) @@ -209,105 +201,132 @@ class KOmegaSSTModelConstants(Flow360BaseModel): class TurbulenceModelSolver(GenericSolverSettings, metaclass=ABCMeta): - """:class:`TurbulenceModelSolver` class for setting up turbulence model solver - - Parameters - ---------- - absoluteTolerance : - Tolerance for the NS residual, below which the solver goes to the next physical step - - relativeTolerance : - Tolerance to the relative residual, below which the solver goes to the next physical step. Relative residual is - defined as the ratio of the current pseudoStep’s residual to the maximum residual present in the first - 10 pseudoSteps within the current physicalStep. NOTE: relativeTolerance is ignored in steady simulations and - only absoluteTolerance is used as the convergence criterion - - CFL_multiplier : - Factor to the CFL definitions defined in “timeStepping” section - - linearIterations : - Number of linear solver iterations - - updateJacobianFrequency : - Frequency at which the jacobian is updated. - - equationEvalFrequency : - Frequency at which to update the NS equation in loosely-coupled simulations - - maxForceJacUpdatePhysicalSteps : - When which physical steps, the jacobian matrix is updated every pseudo step - - orderOfAccuracy : - Order of accuracy in space - - reconstruction_gradient_limiter : - The strength of gradient limiter used in reconstruction of solution variables at the faces (specified in the - range [0.0, 2.0]). 0.0 corresponds to setting the gradient equal to zero, and 2.0 means no limiting. - - quadratic_constitutive_relation : bool, optional - Use quadratic constitutive relation for turbulence shear stress tensor instead of Boussinesq Approximation - - DDES : bool, optional - Enables Delayed Detached Eddy Simulation. Supported for both SpalartAllmaras and kOmegaSST turbulence models, - with and without AmplificationFactorTransport transition model enabled. - - grid_size_for_LES : Literal['maxEdgeLength', 'meanEdgeLength'], optional - Specifes the length used for the computation of LES length scale. The allowed inputs are "maxEdgeLength" - (default) and "meanEdgeLength" - - modeling_constants : - Here, user can change the default values used for DDES coefficients in the solver: - SpalartAllmaras: "C_DES" (= 0.72), "C_d" (= 8.0) - kOmegaSST: "C_DES1" (= 0.78), "C_DES2" (= 0.61), "C_d1" (= 20.0), "C_d2" (= 3.0) - (values shown in the parentheses are the default values used in Flow360) - An example with kOmegaSST mode would be: {"C_DES1": 0.85, "C_d1": 8.0} - - Returns - ------- - :class:`TurbulenceModelSolver` - An instance of the component class TurbulenceModelSolver. + """:class:`TurbulenceModelSolver` class for setting up turbulence model solver. + For more information on setting up the numerical parameters for the turbulence model solver, + refer to :ref:`the turbulence model solver knowledge base `. Example ------- >>> ts = TurbulenceModelSolver(absolute_tolerance=1e-10) """ - CFL_multiplier: PositiveFloat = pd.Field(2.0) - type_name: str = pd.Field() - absolute_tolerance: PositiveFloat = pd.Field(1e-8) - equation_evaluation_frequency: PositiveInt = pd.Field(4) - DDES: bool = pd.Field(False) - grid_size_for_LES: Literal["maxEdgeLength", "meanEdgeLength"] = pd.Field("maxEdgeLength") - reconstruction_gradient_limiter: pd.confloat(ge=0, le=2) = pd.Field(1.0) - quadratic_constitutive_relation: bool = pd.Field(False) - modeling_constants: Optional[TurbulenceModelConstants] = pd.Field(discriminator="type_name") - update_jacobian_frequency: PositiveInt = pd.Field(4) - max_force_jac_update_physical_steps: NonNegativeInt = pd.Field(0) + CFL_multiplier: PositiveFloat = pd.Field( + 2.0, + description="Factor to the CFL definitions defined in the " + + ":ref:`Time Stepping ` section.", + ) + type_name: str = pd.Field( + description=":code:`SpalartAllmaras`, :code:`kOmegaSST`, or :code:`None`." + ) + absolute_tolerance: PositiveFloat = pd.Field( + 1e-8, + description="Tolerance for the turbulence model residual, below which the solver progresses to the " + + "next physical step (unsteady) or completes the simulation (steady).", + ) + equation_evaluation_frequency: PositiveInt = pd.Field( + 4, description="Frequency at which to update the turbulence equation." + ) + DDES: bool = pd.Field( + False, + description=":code:`True` enables Delayed Detached Eddy Simulation. " + + "Supported for both SpalartAllmaras and kOmegaSST turbulence models, " + + "with and without AmplificationFactorTransport transition model enabled.", + ) + grid_size_for_LES: Literal["maxEdgeLength", "meanEdgeLength"] = pd.Field( + "maxEdgeLength", + description="Specifes the length used for the computation of LES length scale. " + + "The allowed inputs are :code:`maxEdgeLength` and :code:`meanEdgeLength`.", + ) + reconstruction_gradient_limiter: pd.confloat(ge=0, le=2) = pd.Field( + 1.0, + description="The strength of gradient limiter used in reconstruction of solution " + + "variables at the faces (specified in the range [0.0, 2.0]). 0.0 corresponds to " + + "setting the gradient equal to zero, and 2.0 means no limiting.", + ) + quadratic_constitutive_relation: bool = pd.Field( + False, + description="Use quadratic constitutive relation for turbulence shear stress tensor " + + "instead of Boussinesq Approximation.", + ) + modeling_constants: Optional[TurbulenceModelConstants] = pd.Field( + discriminator="type_name", + description=" A :class:`TurbulenceModelConstants` object containing the DDES coefficients " + + "in the solver: **SpalartAllmaras**: :code:`C_DES` (= 0.72), :code:`C_d` (= 8.0)," + + '**kOmegaSST**: :code:`"C_DES1"` (= 0.78), ' + + ":code:`C_DES2` (= 0.61), :code:`C_d1` (= 20.0), :code:`C_d2` (= 3.0), " + + "*(values shown in the parentheses are the default values used in Flow360).*", + ) + update_jacobian_frequency: PositiveInt = pd.Field( + 4, description="Frequency at which the jacobian is updated." + ) + max_force_jac_update_physical_steps: NonNegativeInt = pd.Field( + 0, + description="For physical steps less than the input value, the jacobian matrix is " + + "updated every pseudo-step overriding the :paramref:`update_jacobian_frequency` value.", + ) - linear_solver: LinearSolver = pd.Field(LinearSolver(max_iterations=20)) + linear_solver: LinearSolver = pd.Field( + LinearSolver(max_iterations=20), + description="Linear solver settings, see :class:`LinearSolver` documentation.", + ) class KOmegaSST(TurbulenceModelSolver): - """:class:`KOmegaSST` class""" + """ + :class:`KOmegaSST` class for setting up the turbulence solver based on the SST k-omega model. + + Example + ------- + >>> ts = KOmegaSST( + ... absolute_tolerance=1e-10, + ... linear_solver=LinearSolver(max_iterations=25), + ... update_jacobian_frequency=2, + ... equation_evaluation_frequency=1, + ... ) + """ type_name: Literal["kOmegaSST"] = pd.Field("kOmegaSST", frozen=True) - modeling_constants: KOmegaSSTModelConstants = pd.Field(KOmegaSSTModelConstants()) + modeling_constants: KOmegaSSTModelConstants = pd.Field( + KOmegaSSTModelConstants(), + description="A :class:`KOmegaSSTModelConstants` object containing the coefficients " + + "used in the SST k-omega model. For the default values used in Flow360, " + + "please refer to :class:`KOmegaSSTModelConstants`.", + ) class SpalartAllmaras(TurbulenceModelSolver): - """:class:`SpalartAllmaras` class""" + """ + :class:`SpalartAllmaras` class for setting up the turbulence solver based on the Spalart-Allmaras model. + + Example + ------- + >>> ts = SpalartAllmaras( + ... absolute_tolerance=1e-10, + ... linear_solver=LinearSolver(max_iterations=25), + ... update_jacobian_frequency=2, + ... equation_evaluation_frequency=1, + ... ) + """ type_name: Literal["SpalartAllmaras"] = pd.Field("SpalartAllmaras", frozen=True) rotation_correction: bool = pd.Field(False) modeling_constants: Optional[SpalartAllmarasModelConstants] = pd.Field( - SpalartAllmarasModelConstants() + SpalartAllmarasModelConstants(), + description="A :class:`SpalartAllmarasModelConstants` object containing the coefficients " + + "used in the Spalart-Allmaras model. For the default values used in Flow360, " + + "please refer to :class:`SpalartAllmarasModelConstants`.", + ) + reconstruction_gradient_limiter: Optional[pd.confloat(ge=0, le=2)] = pd.Field( + 0.5, + description="The strength of gradient limiter used in reconstruction of solution " + + "variables at the faces (specified in the range [0.0, 2.0]). 0.0 corresponds to " + + "setting the gradient equal to zero, and 2.0 means no limiting.", ) - reconstruction_gradient_limiter: Optional[pd.confloat(ge=0, le=2)] = pd.Field(0.5) class NoneSolver(Flow360BaseModel): - """:class:`SolverNone` class""" + """:class:`NoneSolver` class for disabling the turbulence solver.""" type_name: Literal["None"] = pd.Field("None", frozen=True) @@ -320,56 +339,41 @@ class NoneSolver(Flow360BaseModel): class HeatEquationSolver(GenericSolverSettings): """:class:`HeatEquationSolver` class for setting up heat equation solver. - - Parameters - ---------- - - equation_evaluation_frequency : PositiveInt, optional - Frequency at which to solve the heat equation in conjugate heat transfer simulations - - - linear_solver_config : LinearSolver, optional - Linear solver settings, see LinearSolver documentation. - - Returns - ------- - :class:`HeatEquationSolver` - An instance of the component class HeatEquationSolver. - - Example ------- >>> he = HeatEquationSolver( - equation_evaluation_frequency=10, - linear_solver_config=LinearSolver( - max_iterations=50, - absoluteTolerance=1e-10 - ) - ) + ... equation_evaluation_frequency=10, + ... linear_solver_config=LinearSolver( + ... max_iterations=50, + ... absoluteTolerance=1e-10 + ... ) + ... ) """ type_name: Literal["HeatEquation"] = pd.Field("HeatEquation", frozen=True) - absolute_tolerance: PositiveFloat = pd.Field(1e-9) - equation_evaluation_frequency: PositiveInt = pd.Field(10) - order_of_accuracy: Literal[2] = pd.Field(2) + absolute_tolerance: PositiveFloat = pd.Field( + 1e-9, + description="Absolute residual tolerance that determines the convergence of the heat equation in " + + "conjugate heat transfer. This value should be the same or higher than the absolute tolerance " + + "for the linear solver by a small margin.", + ) + equation_evaluation_frequency: PositiveInt = pd.Field( + 10, + description="Frequency at which to solve the heat equation in conjugate heat transfer simulations.", + ) + order_of_accuracy: Literal[2] = pd.Field(2, description="Order of accuracy in space.") linear_solver: LinearSolver = pd.Field( - LinearSolver(max_iterations=50, absolute_tolerance=1e-10) + LinearSolver(max_iterations=50, absolute_tolerance=1e-10), + description="Linear solver settings, see :class:`LinearSolver` documentation.", ) class TransitionModelSolver(GenericSolverSettings): - """:class:`TransitionModelSolver` class for setting up transition model solver - - Parameters - ---------- + """:class:`TransitionModelSolver` class for setting up transition model solver. + For more information on setting up the numerical parameters for the transition model solver, + refer to :ref:`the transition model solver knowledge base `. - (...) - - Returns - ------- - :class:`TransitionModelSolver` - An instance of the component class TransitionModelSolver. Example ------- @@ -379,19 +383,54 @@ class TransitionModelSolver(GenericSolverSettings): type_name: Literal["AmplificationFactorTransport"] = pd.Field( "AmplificationFactorTransport", frozen=True ) - CFL_multiplier: PositiveFloat = pd.Field(2.0) - absolute_tolerance: PositiveFloat = pd.Field(1e-7) - equation_evaluation_frequency: PositiveInt = pd.Field(4) - turbulence_intensity_percent: Optional[pd.confloat(ge=0.03, le=2.5)] = pd.Field(None) + CFL_multiplier: PositiveFloat = pd.Field( + 2.0, + description="Factor to the CFL definitions defined in the " + + ":ref:`Time Stepping ` section.", + ) + absolute_tolerance: PositiveFloat = pd.Field( + 1e-7, + description="Tolerance for the transition model residual, below which the solver progresses to " + + "the next physical step (unsteady) or completes the simulation (steady).", + ) + equation_evaluation_frequency: PositiveInt = pd.Field( + 4, description="Frequency at which to update the transition equation." + ) + turbulence_intensity_percent: Optional[pd.confloat(ge=0.03, le=2.5)] = pd.Field( + 1.0, + description=":ref:`Turbulence Intensity `, Range from [0.03-2.5]. " + + "Only valid when :paramref:`N_crit` is not specified.", + ) # pylint: disable=invalid-name - N_crit: Optional[pd.confloat(ge=1.0, le=11.0)] = pd.Field(None) - update_jacobian_frequency: PositiveInt = pd.Field(4) - max_force_jac_update_physical_steps: NonNegativeInt = pd.Field(0) - reconstruction_gradient_limiter: Optional[pd.confloat(ge=0.0, le=2.0)] = pd.Field(1.0) + N_crit: Optional[pd.confloat(ge=1.0, le=11.0)] = pd.Field( + None, + description=":ref:`Critical Amplification Factor `, Range from [1-11]. " + + "Only valid when :paramref:`turbulence_intensity_percent` is not specified.", + ) + update_jacobian_frequency: PositiveInt = pd.Field( + 4, description="Frequency at which the jacobian is updated." + ) + max_force_jac_update_physical_steps: NonNegativeInt = pd.Field( + 0, + description="For physical steps less than the input value, the jacobian matrix " + + "is updated every pseudo-step overriding the :paramref:`update_jacobian_frequency` value.", + ) - trip_regions: Optional[EntityList[Box]] = pd.Field(None) + reconstruction_gradient_limiter: Optional[pd.confloat(ge=0.0, le=2.0)] = pd.Field( + 1.0, + description="The strength of gradient limiter used in reconstruction of solution " + + "variables at the faces (specified in the range [0.0, 2.0]). 0.0 corresponds to " + + "setting the gradient equal to zero, and 2.0 means no limiting.", + ) - linear_solver: LinearSolver = pd.Field(LinearSolver(max_iterations=20)) + trip_regions: Optional[EntityList[Box]] = pd.Field( + None, description="A list of :class:`~flow360.Box` entities defining the trip zones." + ) + + linear_solver: LinearSolver = pd.Field( + LinearSolver(max_iterations=20), + description="Linear solver settings, see :class:`LinearSolver` documentation.", + ) @pd.model_validator(mode="after") def _set_aft_ncrit(self) -> Self: diff --git a/flow360/component/simulation/models/surface_models.py b/flow360/component/simulation/models/surface_models.py index 0ca9d5afa..ba35b0c67 100644 --- a/flow360/component/simulation/models/surface_models.py +++ b/flow360/component/simulation/models/surface_models.py @@ -42,63 +42,94 @@ class BoundaryBase(Flow360BaseModel, metaclass=ABCMeta): class BoundaryBaseWithTurbulenceQuantities(BoundaryBase, metaclass=ABCMeta): """Boundary base with turbulence quantities""" - turbulence_quantities: Optional[TurbulenceQuantitiesType] = pd.Field(None) + turbulence_quantities: Optional[TurbulenceQuantitiesType] = pd.Field( + None, + description="The turbulence related quantities definition." + + "See :func:`TurbulenceQuantities` documentation.", + ) class HeatFlux(SingleAttributeModel): - """Heat flux""" + """ + :class:`HeatFlux` class to specify the heat flux for `Wall` boundary condition + via :paramref:`Wall.heat_spec`. + """ type_name: Literal["HeatFlux"] = pd.Field("HeatFlux", frozen=True) - value: Union[HeatFluxType, pd.StrictStr] = pd.Field() + value: Union[HeatFluxType, pd.StrictStr] = pd.Field(description="The heat flux value.") class Temperature(SingleAttributeModel): - """Temperature""" + """ + :class:`Temperature` class to specify the temperature for `Wall` or `Inflow` + boundary condition via :paramref:`Wall.heat_spec`/ + :paramref:`Inflow.spec`. + """ type_name: Literal["Temperature"] = pd.Field("Temperature", frozen=True) # pylint: disable=no-member - value: Union[TemperatureType.Positive, pd.StrictStr] = pd.Field() + value: Union[TemperatureType.Positive, pd.StrictStr] = pd.Field( + description="The temperature value." + ) class TotalPressure(SingleAttributeModel): - """Total pressure""" + """ + :class:`TotalPressure` class to specify the total pressure for `Inflow` + boundary condition via :paramref:`Inflow.spec`. + """ type_name: Literal["TotalPressure"] = pd.Field("TotalPressure", frozen=True) # pylint: disable=no-member - value: PressureType.Positive = pd.Field() + value: PressureType.Positive = pd.Field(description="The total pressure value.") class Pressure(SingleAttributeModel): - """Pressure""" + """ + :class:`Pressure` class to specify the pressure for `Outflow` + boundary condition via :paramref:`Outflow.spec`. + """ type_name: Literal["Pressure"] = pd.Field("Pressure", frozen=True) # pylint: disable=no-member - value: PressureType.Positive = pd.Field() + value: PressureType.Positive = pd.Field(description="The pressure value.") class MassFlowRate(SingleAttributeModel): - """Mass flow rate""" + """ + :class:`MassFlowRate` class to specify the mass flow rate for `Inflow` or `Outflow` + boundary condition via :paramref:`Inflow.spec`/:paramref:`Outflow.spec`. + """ type_name: Literal["MassFlowRate"] = pd.Field("MassFlowRate", frozen=True) # pylint: disable=no-member - value: MassFlowRateType.NonNegative = pd.Field() + value: MassFlowRateType.NonNegative = pd.Field(description="The mass flow rate.") class Mach(SingleAttributeModel): - """Mach""" + """ + :class:`Mach` class to specify Mach number for the `Inflow` + boundary condition via :paramref:`Inflow.spec`. + """ type_name: Literal["Mach"] = pd.Field("Mach", frozen=True) - value: pd.NonNegativeFloat = pd.Field() + value: pd.NonNegativeFloat = pd.Field(description="The Mach number.") class Translational(Flow360BaseModel): - """Translational periodicity""" + """ + :class:`Translational` class to specify translational periodic + boundary condition via :paramref:`Periodic.spec`. + """ type_name: Literal["Translational"] = pd.Field("Translational", frozen=True) class Rotational(Flow360BaseModel): - """Rotational periodicity""" + """ + :class:`Rotational` class to specify rotational periodic + boundary condition via :paramref:`Periodic.spec`. + """ type_name: Literal["Rotational"] = pd.Field("Rotational", frozen=True) # pylint: disable=fixme @@ -112,83 +143,140 @@ class Rotational(Flow360BaseModel): class Wall(BoundaryBase): - """Replace Flow360Param: - - NoSlipWall - - IsothermalWall - - HeatFluxWall - - WallFunction - - SolidIsothermalWall - - SolidAdiabaticWall + """ + :class:`Wall` class defines the Wall boundary conditions below based on the input: + - NoSlipWall + - IsothermalWall + - HeatFluxWall + - WallFunction + - SolidIsothermalWall + - SolidAdiabaticWall """ - name: Optional[str] = pd.Field(None) + name: Optional[str] = pd.Field(None, description="Name of the `Wall` boundary condition.") type: Literal["Wall"] = pd.Field("Wall", frozen=True) - use_wall_function: bool = pd.Field(False) - velocity: Optional[VelocityVectorType] = pd.Field(None) - heat_spec: Optional[Union[HeatFlux, Temperature]] = pd.Field(None, discriminator="type_name") + use_wall_function: bool = pd.Field( + False, + description="Specify if use wall functions to estimate the velocity field " + + "close to the solid boundaries.", + ) + velocity: Optional[VelocityVectorType] = pd.Field( + None, description="Prescribe a tangential velocity on the wall." + ) + heat_spec: Optional[Union[HeatFlux, Temperature]] = pd.Field( + None, + discriminator="type_name", + description="Specify the heat flux or temperature at the `Wall` boundary.", + ) class Freestream(BoundaryBaseWithTurbulenceQuantities): - """Freestream""" + """ + :class:`Freestream` defines the Freestream condition. + """ - name: Optional[str] = pd.Field(None) + name: Optional[str] = pd.Field(None, description="Name of the `Freestream` boundary condition.") type: Literal["Freestream"] = pd.Field("Freestream", frozen=True) - velocity: Optional[VelocityVectorType] = pd.Field(None) - entities: EntityList[Surface, GhostSurface] = pd.Field(alias="surfaces") + velocity: Optional[VelocityVectorType] = pd.Field( + None, + description="The default values are set according to the " + + ":paramref:`AerospaceCondition.alpha` and :paramref:`AerospaceCondition.beta` angles. " + + "Optionally, an expression for each of the velocity components can be specified.", + ) + entities: EntityList[Surface, GhostSurface] = pd.Field( + alias="surfaces", + description="A list of :class:`Surface` entities with " + + "the `Freestream` boundary condition imposed.", + ) class Outflow(BoundaryBase): - """Replace Flow360Param: - - SubsonicOutflowPressure - - SubsonicOutflowMach - - MassOutflow + """ + :class:`Outflow` defines the Outflow boundary conditions below based on the input: + - SubsonicOutflowPressure + - SubsonicOutflowMach + - MassOutflow """ - name: Optional[str] = pd.Field(None) + name: Optional[str] = pd.Field(None, description="Name of the `Outflow` boundary condition.") type: Literal["Outflow"] = pd.Field("Outflow", frozen=True) - spec: Union[Pressure, MassFlowRate, Mach] = pd.Field(discriminator="type_name") + spec: Union[Pressure, MassFlowRate, Mach] = pd.Field( + discriminator="type_name", + description="Specify the static pressure, mass flow rate or Mach number at the `Outflow` boundary.", + ) class Inflow(BoundaryBaseWithTurbulenceQuantities): - """Replace Flow360Param: - - SubsonicInflow - - MassInflow + """ + :class:`Inflow` defines the Inflow boundary condition below based on the input: + - SubsonicInflow + - MassInflow """ - name: Optional[str] = pd.Field(None) + name: Optional[str] = pd.Field(None, description="Name of the `Inflow` boundary condition.") type: Literal["Inflow"] = pd.Field("Inflow", frozen=True) # pylint: disable=no-member - total_temperature: TemperatureType.Positive = pd.Field() - velocity_direction: Optional[Axis] = pd.Field(None) - spec: Union[TotalPressure, MassFlowRate] = pd.Field(discriminator="type_name") + total_temperature: TemperatureType.Positive = pd.Field( + description="Specify the total temperature at the `Inflow` boundary." + ) + velocity_direction: Optional[Axis] = pd.Field( + None, + description=" Direction of the incoming flow. Must be a unit vector pointing " + + "into the volume. If unspecified, the direction will be normal to the surface.", + ) + spec: Union[TotalPressure, MassFlowRate] = pd.Field( + discriminator="type_name", + description="Specify the total pressure or the mass flow rate at the `Inflow` boundary.", + ) class SlipWall(BoundaryBase): - """Slip wall""" + """:class:`SlipWall` class defines the SlipWall boundary condition.""" - name: Optional[str] = pd.Field(None) + name: Optional[str] = pd.Field(None, description="Name of the `SlipWall` boundary condition.") type: Literal["SlipWall"] = pd.Field("SlipWall", frozen=True) - entities: EntityList[Surface, GhostSurface] = pd.Field(alias="surfaces") + entities: EntityList[Surface, GhostSurface] = pd.Field( + alias="surfaces", + description="A list of :class:`Surface` entities with " + + "the `SlipWall` boundary condition imposed.", + ) class SymmetryPlane(BoundaryBase): - """Symmetry plane""" + """ + :class:`SymmetryPlane` defines the `SymmetryPlane` boundary condition. + It is similar to :class:`SlipWall`, but the normal gradient of scalar quantities + are forced to be zero on the symmetry plane. Only planar surfaces are supported. + """ - name: Optional[str] = pd.Field(None) + name: Optional[str] = pd.Field( + None, description="Name of the `SymmetryPlane` boundary condition." + ) type: Literal["SymmetryPlane"] = pd.Field("SymmetryPlane", frozen=True) - entities: EntityList[Surface, GhostSurface] = pd.Field(alias="surfaces") + entities: EntityList[Surface, GhostSurface] = pd.Field( + alias="surfaces", + description="A list of :class:`Surface` entities with " + + "the `SymmetryPlane` boundary condition imposed.", + ) class Periodic(Flow360BaseModel): - """Replace Flow360Param: - - TranslationallyPeriodic - - RotationallyPeriodic + """ + :class:`Periodic` defines the translational or rotational periodic boundary condition. """ - name: Optional[str] = pd.Field(None) + name: Optional[str] = pd.Field(None, description="Name of the `Periodic` boundary condition.") type: Literal["Periodic"] = pd.Field("Periodic", frozen=True) - entity_pairs: UniqueItemList[SurfacePair] = pd.Field(alias="surface_pairs") - spec: Union[Translational, Rotational] = pd.Field(discriminator="type_name") + entity_pairs: UniqueItemList[SurfacePair] = pd.Field( + alias="surface_pairs", + description=" Patch name of the matching pair of a :class:`~flow360.Surface` patch. " + + "Needs to be specified for one side of each of the periodic boundary pairs.", + ) + spec: Union[Translational, Rotational] = pd.Field( + discriminator="type_name", + description="Define the type of periodic boundary condition (translational/rotational) " + + "via :class:`Translational`/:class:`Rotational`.", + ) SurfaceModelTypes = Union[ diff --git a/flow360/component/simulation/models/turbulence_quantities.py b/flow360/component/simulation/models/turbulence_quantities.py index e68abc3fd..2a15d808f 100644 --- a/flow360/component/simulation/models/turbulence_quantities.py +++ b/flow360/component/simulation/models/turbulence_quantities.py @@ -202,7 +202,55 @@ def TurbulenceQuantities( turbulent_length_scale=None, turbulent_intensity=None, ) -> TurbulenceQuantitiesType: - """Return a matching tubulence specification object""" + """ + + :func:`TurbulenceQuantities` function specifies turbulence conditions + for the :class:`~flow360.Inflow` or :class:`~flow360.Freestream` + at boundaries. The turbulence properties that can be + specified are listed below. All values are dimensional. + For valid specifications as well as the default values, + please refer to :ref:`knowledge base`. + + Parameters + ---------- + viscosity_ratio : >= 0 + The ratio between the turbulent viscosity and freestream laminar + viscosity. Applicable to both :class:`~flow360.KOmegaSST` and + `~flow360.SpalartAllmaras`. Its value will be converted to + :paramref:`modifiedTurbulentViscosityRatio` when using + SpalartAllmaras model. + modified_viscosity_ratio : >= 0 + The ratio between the modified turbulent viscosity (in SA model) and + freestream laminar viscosity. + Applicable to :class:`~flow360.SpalartAllmaras`. + modified_viscosity : >=0 + The modified turbulent viscosity, aka nuHat. + Applicable to :class:`~flow360.SpalartAllmaras`. + specific_dissipation_rate : >= 0 + The turbulent specific dissipation rate. Applicable to :class:`~flow360.KOmegaSST`. + turbulent_kinetic_energy : >=0 + The turbulent kinetic energy. Applicable to :class:`~flow360.KOmegaSST`. + turbulent_length_scale : > 0 + The turbulent length scale is an estimation of the size of + the eddies that are modeled/not resolved. + Applicable to :class:`~flow360.KOmegaSST`. + turbulent_intensity : >= 0 + The turbulent intensity is related to the turbulent kinetic energy by + :math:`k = 1.5(U_{ref} * I)^2` where :math:`k` is the dimensional + turbulent kinetic energy, :math:`U_{ref}` is the reference velocity + and :math:`I` is the turbulent intensity. The value represents the + actual magnitude of intensity instead of percentage. Applicable to + :class:`~flow360.KOmegaSST`. + + Returns + ------- + A matching tubulence specification object. + + Raises + ------- + ValueError + If the TurbulenceQuantities inputs do not represent a valid specification. + """ non_none_arg_count = sum(arg is not None for arg in locals().values()) if non_none_arg_count == 0: return None diff --git a/flow360/component/simulation/models/volume_models.py b/flow360/component/simulation/models/volume_models.py index 252f07200..f677576f6 100644 --- a/flow360/component/simulation/models/volume_models.py +++ b/flow360/component/simulation/models/volume_models.py @@ -51,39 +51,59 @@ class AngleExpression(SingleAttributeModel): - """Angle expression for Rotation""" + """ + :class:`AngleExpression` class for define the angle expression for :paramref:`Rotation.spec`. + """ type_name: Literal["AngleExpression"] = pd.Field("AngleExpression", frozen=True) - value: StringExpression = pd.Field() + value: StringExpression = pd.Field( + description="The expression defining the rotation angle as a function of time." + ) class AngularVelocity(SingleAttributeModel): - """Angular velocity for Rotation""" + """ + :class:`AngularVelocity` class to define the angular velocity for :paramref:`Rotation.spec`. + """ type_name: Literal["AngularVelocity"] = pd.Field("AngularVelocity", frozen=True) - value: AngularVelocityType = pd.Field() + value: AngularVelocityType = pd.Field(description="The value of the angular velocity.") class FromUserDefinedDynamics(Flow360BaseModel): - """Rotation is controlled by user defined dynamics""" + """ + :class:`FromUserDefinedDynamics` class to define the rotation + controlled by user defined dynamics for :paramref:`Rotation.spec`. + """ type_name: Literal["FromUserDefinedDynamics"] = pd.Field("FromUserDefinedDynamics", frozen=True) class ExpressionInitialConditionBase(Flow360BaseModel): - """:class:`ExpressionInitialCondition` class""" + """ + :class:`ExpressionInitialCondition` class for specifying the intial conditions of + :paramref:`Fluid.initial_condition`. + """ type: Literal["expression"] = pd.Field("expression", frozen=True) - constants: Optional[Dict[str, str]] = pd.Field(None) + constants: Optional[Dict[str, str]] = pd.Field( + None, description="The expression for the initial condition." + ) # pylint: disable=missing-class-docstring class NavierStokesInitialCondition(ExpressionInitialConditionBase): - rho: str = pd.Field() - u: str = pd.Field() - v: str = pd.Field() - w: str = pd.Field() - p: str = pd.Field() + """ + :class:`NavierStokesInitialCondition` class for specifying the + :paramref:`Fluid.initial_condition`. + + """ + + rho: str = pd.Field(description="Density") + u: str = pd.Field(description="X-direction velocity") + v: str = pd.Field(description="Y-direction velocity") + w: str = pd.Field(description="Z-direction velocity") + p: str = pd.Field(description="Pressure") class NavierStokesModifiedRestartSolution(NavierStokesInitialCondition): @@ -91,7 +111,12 @@ class NavierStokesModifiedRestartSolution(NavierStokesInitialCondition): class HeatEquationInitialCondition(ExpressionInitialConditionBase): - temperature: str = pd.Field() + """ + :class:`HeatEquationInitialCondition` class for specifying the + :paramref:`Solid.initial_condition` of heat equation. + """ + + temperature: str = pd.Field(description="The initial temperature value") class PDEModelBase(Flow360BaseModel): @@ -106,19 +131,34 @@ class PDEModelBase(Flow360BaseModel): class Fluid(PDEModelBase): """ - General FluidDynamics volume model that contains all the common fields every fluid dynamics zone should have. + :class:`Fluid` class for setting up the volume model that contains + all the common fields every fluid dynamics zone should have. """ type: Literal["Fluid"] = pd.Field("Fluid", frozen=True) - navier_stokes_solver: NavierStokesSolver = pd.Field(NavierStokesSolver()) - turbulence_model_solver: TurbulenceModelSolverType = pd.Field(SpalartAllmaras()) - transition_model_solver: TransitionModelSolverType = pd.Field(NoneSolver()) + navier_stokes_solver: NavierStokesSolver = pd.Field( + NavierStokesSolver(), + description="Navier-Stokes solver settings, see " + + ":class:`NavierStokesSolver` documentation.", + ) + turbulence_model_solver: TurbulenceModelSolverType = pd.Field( + SpalartAllmaras(), + description="Turbulence model solver settings, see " + + ":class:`~flow360.TurbulenceModelSolver` documentation.", + ) + transition_model_solver: TransitionModelSolverType = pd.Field( + NoneSolver(), + description="Transition solver settings, see " + + ":class:`~flow360.TransitionModelSolver` documentation.", + ) - material: FluidMaterialTypes = pd.Field(Air()) + material: FluidMaterialTypes = pd.Field(Air(), description="The material propetry of fluid.") initial_condition: Optional[ Union[NavierStokesModifiedRestartSolution, NavierStokesInitialCondition] - ] = pd.Field(None, discriminator="type") + ] = pd.Field( + None, discriminator="type", description="The initial condition of the fluid solver." + ) # pylint: disable=fixme # fixme: Add support for other initial conditions @@ -126,43 +166,37 @@ class Fluid(PDEModelBase): class Solid(PDEModelBase): """ - General HeatTransfer volume model that contains all the common fields every heat transfer zone should have. + :class:`Solid` class for setting up the HeatTransfer volume model that + contains all the common fields every heat transfer zone should have. """ - name: Optional[str] = pd.Field(None) + name: Optional[str] = pd.Field(None, description="Name of the `Solid` model.") type: Literal["Solid"] = pd.Field("Solid", frozen=True) - entities: EntityList[GenericVolume] = pd.Field(alias="volumes") + entities: EntityList[GenericVolume] = pd.Field( + alias="volumes", + description="The list of :class:`GenericVolume` " + + "entities on which the heat transfer equation is solved.", + ) - material: SolidMaterialTypes = pd.Field() + material: SolidMaterialTypes = pd.Field(description="The material property of solid.") - heat_equation_solver: HeatEquationSolver = pd.Field(HeatEquationSolver()) - volumetric_heat_source: Union[HeatSourceType, pd.StrictStr] = pd.Field(0) + heat_equation_solver: HeatEquationSolver = pd.Field( + HeatEquationSolver(), + description="Heat equation solver settings, see " + + ":class:`HeatEquationSolver` documentation.", + ) + volumetric_heat_source: Union[HeatSourceType, pd.StrictStr] = pd.Field( + 0, description="The volumetric heat source." + ) - initial_condition: Optional[HeatEquationInitialCondition] = pd.Field(None) + initial_condition: Optional[HeatEquationInitialCondition] = pd.Field( + None, description="The initial condition of the heat equation solver." + ) # pylint: disable=duplicate-code class ForcePerArea(Flow360BaseModel): - """:class:`ForcePerArea` class for setting up force per area for Actuator Disk - - Parameters - ---------- - radius : LengthType.Array - Radius of the sampled locations in grid unit - - thrust : PressureType.Array - Force per area in the axial direction, positive means the axial force follows the same direction as axisThrust. - It is non-dimensional: trustPerArea[SI=N/m2]/rho_inf/C_inf^2 - - circumferential : PressureType.Array - Force per area in the circumferential direction, positive means the circumferential force follows the same - direction as axisThrust with the right hand rule. It is non-dimensional: - circumferentialForcePerArea[SI=N/m2]/rho_inf/C_inf^2 - - Returns - ------- - :class:`ForcePerArea` - An instance of the component class ForcePerArea. + """:class:`ForcePerArea` class for setting up force per area for Actuator Disk. Example ------- @@ -171,9 +205,18 @@ class ForcePerArea(Flow360BaseModel): TODO: Use dimensioned values """ - radius: LengthType.Array # pylint: disable=no-member - thrust: PressureType.Array # pylint: disable=no-member - circumferential: PressureType.Array # pylint: disable=no-member + # pylint: disable=no-member + radius: LengthType.Array = pd.Field(description="Radius of the sampled locations in grid unit.") + # pylint: disable=no-member + thrust: PressureType.Array = pd.Field( + description="Dimensional force per area in the axial direction, positive means the axial " + + "force follows the same direction as the thrust axis. " + ) + # pylint: disable=no-member + circumferential: PressureType.Array = pd.Field( + description="Dimensional force per area in the circumferential direction, positive means the " + + "circumferential force follows the same direction as the thrust axis with the right hand rule. " + ) # pylint: disable=no-self-argument, missing-function-docstring @pd.model_validator(mode="before") @@ -194,65 +237,144 @@ def validate_consistent_array_length(cls, values): class ActuatorDisk(Flow360BaseModel): - """Same as Flow360Param ActuatorDisks. + """:class:`ActuatorDisk` class for setting up the inputs for an Actuator Disk. + Please refer to the :ref:`actuator disk knowledge base ` for further information. Note that `center`, `axis_thrust`, `thickness` can be acquired from `entity` so they are not required anymore. """ - entities: EntityList[Cylinder] = pd.Field(alias="volumes") - force_per_area: ForcePerArea = pd.Field() - name: Optional[str] = pd.Field(None) + entities: EntityList[Cylinder] = pd.Field( + alias="volumes", + description="The list of :class:`Cylinder` entities for the `ActuatorDisk` model", + ) + force_per_area: ForcePerArea = pd.Field( + description="The force per area input for the `ActuatorDisk` model. " + + "See :class:`ForcePerArea` documentation." + ) + name: Optional[str] = pd.Field(None, description="Name of the `ActuatorDisk` model.") type: Literal["ActuatorDisk"] = pd.Field("ActuatorDisk", frozen=True) class BETDiskTwist(Flow360BaseModel): - """:class:`BETDiskTwist` class""" + """:class:`BETDiskTwist` class for setting up the :paramref:`BETDisk.twists`.""" # TODO: Use dimensioned values, why optional? - radius: Optional[float] = pd.Field(None) - twist: Optional[float] = pd.Field(None) + radius: Optional[float] = pd.Field(None, description="A list of radial locations.") + twist: Optional[float] = pd.Field( + None, + description="The twist in degrees as a function of radial location. " + + "Entries in the list must already be sorted by radius.", + ) class BETDiskChord(Flow360BaseModel): - """:class:`BETDiskChord` class""" + """:class:`BETDiskChord` class for setting up the :paramref:`BETDisk.chords`.""" # TODO: Use dimensioned values, why optional? - radius: Optional[float] = pd.Field(None) - chord: Optional[float] = pd.Field(None) + radius: Optional[float] = pd.Field(None, description="A list of radial locations.") + chord: Optional[float] = pd.Field( + None, + description="The blade chord as a function of the radial location. " + + "Entries in the list must already be sorted by radius.", + ) class BETDiskSectionalPolar(Flow360BaseModel): - """:class:`BETDiskSectionalPolar` class""" + """:class:`BETDiskSectionalPolar` class for setting up :paramref:`BETDisk.sectional_polars` + for :class:`BETDisk`. There are two variables, “lift_coeffs” and “drag_coeffs”, + need to be set up as 3D arrays (implemented as nested lists). + The first index of the array corresponds to the :paramref:`BETDisk.mach_numbers` + of the specified polar data. + The second index of the array corresponds to the :paramref:`BETDisk.reynolds_numbers` + of the polar data. + The third index corresponds to the :paramref:`BETDisk.alphas`. + The value specifies the lift or drag coefficient, respectively. + """ - lift_coeffs: Optional[List[List[List[float]]]] = pd.Field() - drag_coeffs: Optional[List[List[List[float]]]] = pd.Field() + lift_coeffs: Optional[List[List[List[float]]]] = pd.Field( + description="The 3D arrays specifying the list coefficient." + ) + drag_coeffs: Optional[List[List[List[float]]]] = pd.Field( + description="The 3D arrays specifying the drag coefficient." + ) # pylint: disable=no-member class BETDisk(Flow360BaseModel): - """Same as Flow360Param BETDisk. + """:class:`BETDisk` class for defining the Blade Element Theory (BET) model inputs. + For detailed information on the parameters, please refer to the :ref:`BET knowledge Base `. + To generate the sectional polars the BET translators can be used which are + outlined :ref:`here ` + with best-practices for the sectional polars inputs available :ref:`here `. + A case study of the XV-15 rotor using the steady BET Disk method is available + in :ref:`Case Studies `. + Because a transient BET Line simulation is simply a time-accurate version of a steady-state + BET Disk simulation, most of the parameters below are applicable to both methods. Note that `center_of_rotation`, `axis_of_rotation`, `radius`, `thickness` can be acquired from `entity` so they are not required anymore. """ - name: Optional[str] = pd.Field(None) + name: Optional[str] = pd.Field(None, description="Name of the `BETDisk` model.") type: Literal["BETDisk"] = pd.Field("BETDisk", frozen=True) entities: EntityList[Cylinder] = pd.Field(alias="volumes") - rotation_direction_rule: Literal["leftHand", "rightHand"] = pd.Field("rightHand") - number_of_blades: pd.StrictInt = pd.Field(gt=0, le=10) - omega: AngularVelocityType.NonNegative = pd.Field() - chord_ref: LengthType.Positive = pd.Field() - n_loading_nodes: pd.StrictInt = pd.Field(gt=0, le=1000) - blade_line_chord: LengthType.NonNegative = pd.Field(0) - initial_blade_direction: Optional[Axis] = pd.Field(None) - tip_gap: Union[Literal["inf"], LengthType.NonNegative] = pd.Field("inf") - mach_numbers: List[pd.NonNegativeFloat] = pd.Field() - reynolds_numbers: List[pd.PositiveFloat] = pd.Field() - alphas: List[float] = pd.Field() - twists: List[BETDiskTwist] = pd.Field() - chords: List[BETDiskChord] = pd.Field() - sectional_polars: List[BETDiskSectionalPolar] = pd.Field() - sectional_radiuses: List[float] = pd.Field() + rotation_direction_rule: Literal["leftHand", "rightHand"] = pd.Field( + "rightHand", + description='The rule for rotation direction and thrust direction, "rightHand" or "leftHand".', + ) + number_of_blades: pd.StrictInt = pd.Field(gt=0, le=10, description="Number of blades to model.") + omega: AngularVelocityType.NonNegative = pd.Field(description="Rotating speed.") + chord_ref: LengthType.Positive = pd.Field( + description="Dimensional reference chord used to compute sectional blade loadings." + ) + n_loading_nodes: pd.StrictInt = pd.Field( + gt=0, + le=1000, + description="Number of nodes used to compute the sectional thrust and " + + "torque coefficients :math:`C_t` and :math:`C_q`, defined in :ref:`betDiskLoadingNote`.", + ) + blade_line_chord: LengthType.NonNegative = pd.Field( + 0, + description="Dimensional chord to use if performing an unsteady BET Line simulation. " + + "Default of 0.0 is an indication to run a steady BET Disk simulation.", + ) + initial_blade_direction: Optional[Axis] = pd.Field( + None, + description="Orientation of the first blade in the BET model. " + + "Must be specified if performing an unsteady BET Line simulation.", + ) + tip_gap: Union[Literal["inf"], LengthType.NonNegative] = pd.Field( + "inf", + description="Dimensional distance between blade tip and solid bodies to " + + "define a :ref:`tip loss factor `.", + ) + mach_numbers: List[pd.NonNegativeFloat] = pd.Field( + description="Mach numbers associated with airfoil polars provided " + + "in :class:`BETDiskSectionalPolar`." + ) + reynolds_numbers: List[pd.PositiveFloat] = pd.Field( + description="Reynolds numbers associated with the airfoil polars " + + "provided in :class:`BETDiskSectionalPolar`." + ) + alphas: List[float] = pd.Field( + description="Alphas associated with airfoil polars provided in " + + ":class:`BETDiskSectionalPolar` in degrees." + ) + twists: List[BETDiskTwist] = pd.Field( + description="A list of :class:`BETDiskTwist` objects specifying the twist in degrees as a " + + "function of radial location." + ) + chords: List[BETDiskChord] = pd.Field( + description="A list of :class:`BETDiskChord` objects specifying the blade chord as a function " + + "of the radial location. " + ) + sectional_polars: List[BETDiskSectionalPolar] = pd.Field( + description="A list of :class:`BETDiskSectionalPolar` objects for every radial location specified in " + + ":paramref:`sectional_radiuses`." + ) + sectional_radiuses: List[float] = pd.Field( + description="A list of the radial locations in grid units at which :math:`C_l` " + + "and :math:`C_d` are specified in :class:`BETDiskSectionalPolar`." + ) @pd.model_validator(mode="after") @_validator_append_instance_name @@ -295,20 +417,28 @@ def check_bet_disk_3d_coefficients_in_polars(self): class Rotation(Flow360BaseModel): - """Similar to Flow360Param ReferenceFrame. - Note that `center`, `axis` can be acquired from `entity` so they are not required anymore. - Note: Should use the unit system to convert degree or degree per second to radian and radian per second + """ + :class:`Rotation` class for specifying rotation settings. """ - name: Optional[str] = pd.Field(None) + name: Optional[str] = pd.Field(None, description="Name of the `Rotation` model.") type: Literal["Rotation"] = pd.Field("Rotation", frozen=True) - entities: EntityList[GenericVolume, Cylinder] = pd.Field(alias="volumes") + entities: EntityList[GenericVolume, Cylinder] = pd.Field( + alias="volumes", + description="The entity list for the `Rotation` model. " + + "The entity should be :class:`Cylinder` or :class:`GenericVolume` type.", + ) # TODO: Add test for each of the spec specification. spec: Union[AngleExpression, FromUserDefinedDynamics, AngularVelocity] = pd.Field( - discriminator="type_name" + discriminator="type_name", + description="The angular velocity or rotation angle as a function of time.", + ) + parent_volume: Optional[Union[GenericVolume, Cylinder]] = pd.Field( + None, + description="The parent rotating entity in a nested rotation case." + + "The entity should be :class:`Cylinder` or :class:`GenericVolume` type.", ) - parent_volume: Optional[Union[GenericVolume, Cylinder]] = pd.Field(None) @pd.field_validator("entities", mode="after") @classmethod @@ -328,15 +458,31 @@ def _ensure_entities_have_sufficient_attributes(cls, value: EntityList): class PorousMedium(Flow360BaseModel): - """Constains Flow360Param PorousMediumBox and PorousMediumVolumeZone""" + """ + :class:`PorousMedium` class for specifying porous media settings.`. + For further information please refer to the :ref:`porous media knowledge base ` + """ - name: Optional[str] = pd.Field(None) + name: Optional[str] = pd.Field(None, description="Name of the `PorousMedium` model.") type: Literal["PorousMedium"] = pd.Field("PorousMedium", frozen=True) - entities: EntityList[GenericVolume, Box] = pd.Field(alias="volumes") + entities: EntityList[GenericVolume, Box] = pd.Field( + alias="volumes", + description="The entity list for the `PorousMedium` model. " + + "The entity should be :class:`Box` type.", + ) - darcy_coefficient: InverseAreaType.Point = pd.Field() - forchheimer_coefficient: InverseLengthType.Point = pd.Field() - volumetric_heat_source: Optional[Union[HeatSourceType, pd.StrictStr]] = pd.Field(None) + darcy_coefficient: InverseAreaType.Point = pd.Field( + description="Darcy coefficient of the porous media model which determines the scaling of the " + + "viscous loss term. The 3 values define the coefficient for each of the 3 axes defined by " + + "the reference frame of the volume zone." + ) + forchheimer_coefficient: InverseLengthType.Point = pd.Field( + description="Forchheimer coefficient of the porous media model which determines " + + "the scaling of the inertial loss term." + ) + volumetric_heat_source: Optional[Union[HeatSourceType, pd.StrictStr]] = pd.Field( + None, description="The volumetric heat source." + ) # Note: Axes will always come from the entity @pd.field_validator("entities", mode="after") diff --git a/flow360/component/simulation/operating_condition/operating_condition.py b/flow360/component/simulation/operating_condition/operating_condition.py index a29b6381d..f61d5b5db 100644 --- a/flow360/component/simulation/operating_condition/operating_condition.py +++ b/flow360/component/simulation/operating_condition/operating_condition.py @@ -31,6 +31,7 @@ ) from flow360.component.simulation.validation.validation_context import ( CASE, + CaseField, ConditionalField, context_validator, ) @@ -51,26 +52,20 @@ class ThermalStateCache(Flow360BaseModel): class ThermalState(MultiConstructorBaseModel): """ Represents the thermal state of a fluid with specific properties. - - Attributes: - ----------- - temperature : TemperatureType.Positive - The temperature of the fluid, initialized to 288.15 K. This field is frozen and should not be modified after - construction. - density : DensityType.Positive - The density of the fluid, initialized to 1.225 kg/m^3. This field is frozen and should not be modified after - construction. - material : FluidMaterialTypes - The type of fluid material, initialized to Air(). This field is frozen and should not be modified after - construction. """ # pylint: disable=fixme # TODO: romove frozen and throw warning if temperature/density is modified after construction from atmospheric model type_name: Literal["ThermalState"] = pd.Field("ThermalState", frozen=True) - temperature: TemperatureType.Positive = pd.Field(288.15 * u.K, frozen=True) - density: DensityType.Positive = pd.Field(1.225 * u.kg / u.m**3, frozen=True) - material: FluidMaterialTypes = pd.Field(Air(), frozen=True) + temperature: TemperatureType.Positive = pd.Field( + 288.15 * u.K, frozen=True, description="The temperature of the fluid." + ) + density: DensityType.Positive = pd.Field( + 1.225 * u.kg / u.m**3, frozen=True, description="The density of the fluid." + ) + material: FluidMaterialTypes = pd.Field( + Air(), frozen=True, description="The material of the fluid." + ) private_attribute_input_cache: ThermalStateCache = ThermalStateCache() private_attribute_constructor: Literal["from_standard_atmosphere", "default"] = pd.Field( default="default", frozen=True @@ -84,14 +79,49 @@ def from_standard_atmosphere( altitude: LengthType = 0 * u.m, temperature_offset: TemperatureType = 0 * u.K, ): - """Constructs a thermal state from the standard atmosphere model. - - Parameters: - altitude (LengthType): The altitude at which the state is calculated. - temperature_offset (TemperatureType): The offset to be applied to the standard temperature. - - Returns: - ThermalState: The thermal state at the given altitude. + """ + Constructs a :class:`ThermalState` instance from the standard atmosphere model. + + Parameters + ---------- + altitude : LengthType, optional + The altitude at which the thermal state is calculated. Defaults to ``0 * u.m``. + temperature_offset : TemperatureType, optional + The temperature offset to be applied to the standard temperature at the given altitude. + Defaults to ``0 * u.K``. + + Returns + ------- + ThermalState + A thermal state representing the atmospheric conditions at the specified altitude and temperature offset. + + Notes + ----- + - This method uses the :class:`StandardAtmosphereModel` to compute the standard atmospheric + conditions based on the given altitude. + - The ``temperature_offset`` allows for adjustments to the standard temperature, simulating + non-standard atmospheric conditions. + + Examples + -------- + Create a thermal state at an altitude of 10,000 meters: + + >>> thermal_state = ThermalState.from_standard_atmosphere(altitude=10000 * u.m) + >>> thermal_state.temperature + + >>> thermal_state.density + + + Apply a temperature offset of -5 Kelvin at 5,000 meters: + + >>> thermal_state = ThermalState.from_standard_atmosphere( + ... altitude=5000 * u.m, + ... temperature_offset=-5 * u.K + ... ) + >>> thermal_state.temperature + + >>> thermal_state.density + """ standard_atmosphere_model = StandardAtmosphereModel( altitude.in_units(u.m).value, temperature_offset.in_units(u.K).value @@ -182,16 +212,19 @@ class AerospaceConditionCache(Flow360BaseModel): class AerospaceCondition(MultiConstructorBaseModel): - """A specialized GenericReferenceCondition for aerospace applications.""" + """Operating condition for aerospace applications.""" - # pylint: disable=fixme - # TODO: valildate reference_velocity_magnitude defined if velocity_magnitude=0 type_name: Literal["AerospaceCondition"] = pd.Field("AerospaceCondition", frozen=True) - alpha: AngleType = 0 * u.deg - beta: AngleType = 0 * u.deg - velocity_magnitude: Optional[VelocityType.NonNegative] = ConditionalField(context=CASE) + alpha: AngleType = ConditionalField(0 * u.deg, description="The angle of attack.", context=CASE) + beta: AngleType = ConditionalField(0 * u.deg, description="The side slip angle.", context=CASE) + velocity_magnitude: Optional[VelocityType.NonNegative] = ConditionalField( + description="Freestream velocity magnitude.", context=CASE + ) thermal_state: ThermalState = pd.Field(ThermalState(), alias="atmosphere") - reference_velocity_magnitude: Optional[VelocityType.Positive] = None + reference_velocity_magnitude: Optional[VelocityType.Positive] = CaseField( + None, + description="Reference velocity magnitude. Is required when :paramref:`velocity_magnitude` is 0.", + ) private_attribute_input_cache: AerospaceConditionCache = AerospaceConditionCache() # pylint: disable=too-many-arguments, no-self-argument, not-callable @@ -206,11 +239,52 @@ def from_mach( reference_mach: Optional[pd.PositiveFloat] = None, ): """ - Constructs a `AerospaceCondition` from Mach number and thermal state. - - Note: - Decided to move `velocity==0 ref_velocity is not None` check to dedicated validator because user can - still construct by just calling AerospaceCondition() + Constructs an :class:`AerospaceCondition` instance from a Mach number and thermal state. + + Parameters + ---------- + mach : float + The Mach number (non-negative). + alpha : AngleType, optional + The angle of attack. Defaults to ``0 * u.deg``. + beta : AngleType, optional + The side slip angle. Defaults to ``0 * u.deg``. + thermal_state : ThermalState, optional + The atmospheric thermal state. Defaults to a standard :class:`ThermalState`. + reference_mach : float, optional + The reference Mach number (positive). If provided, calculates the reference velocity magnitude. + + Returns + ------- + AerospaceCondition + An instance of :class:`AerospaceCondition` with the calculated velocity magnitude and provided parameters. + + Notes + ----- + - The ``velocity_magnitude`` is calculated as ``mach * thermal_state.speed_of_sound``. + - If ``reference_mach`` is provided, the ``reference_velocity_magnitude`` is calculated as + ``reference_mach * thermal_state.speed_of_sound``. + + Examples + -------- + Create an aerospace condition with a Mach number of 0.85: + + >>> condition = AerospaceCondition.from_mach(mach=0.85) + >>> condition.velocity_magnitude + + + Specify angle of attack and side slip angle: + + >>> condition = AerospaceCondition.from_mach(mach=0.85, alpha=5 * u.deg, beta=2 * u.deg) + + Include a custom thermal state and reference Mach number: + + >>> custom_thermal = ThermalState(temperature=250 * u.K) + >>> condition = AerospaceCondition.from_mach( + ... mach=0.85, + ... thermal_state=custom_thermal, + ... reference_mach=0.8 + ... ) """ velocity_magnitude = mach * thermal_state.speed_of_sound @@ -242,9 +316,6 @@ def mach(self) -> pd.PositiveFloat: """Computes Mach number.""" return self.velocity_magnitude / self.thermal_state.speed_of_sound - # pylint: disable=fixme - # TODO: Add after model validation that reference_velocity_magnitude is set when velocity_magnitude is 0 - # pylint: disable=fixme # TODO: AutomotiveCondition diff --git a/flow360/component/simulation/outputs/output_entities.py b/flow360/component/simulation/outputs/output_entities.py index 77befab19..882352d81 100644 --- a/flow360/component/simulation/outputs/output_entities.py +++ b/flow360/component/simulation/outputs/output_entities.py @@ -5,12 +5,25 @@ import pydantic as pd -from flow360.component.flow360_params.flow360_fields import IsoSurfaceFieldNames from flow360.component.simulation.framework.base_model import Flow360BaseModel from flow360.component.simulation.framework.entity_base import EntityBase from flow360.component.simulation.unit_system import LengthType from flow360.component.types import Axis +# pylint: disable=duplicate-code +# inlined from v1 module to avoid circular import +IsoSurfaceFieldNames = Literal[ + "p", + "rho", + "Mach", + "qcriterion", + "s", + "T", + "Cp", + "mut", + "nuHat", +] + class _OutputItemBase(Flow360BaseModel): name: str = pd.Field() @@ -38,36 +51,45 @@ class _PointEntityBase(EntityBase, metaclass=ABCMeta): class Slice(_SliceEntityBase): - """Slice output item.""" + """:class:`Slice` class for defining a slice for :class:`~flow360.SliceOutput`.""" private_attribute_entity_type_name: Literal["Slice"] = pd.Field("Slice", frozen=True) - normal: Axis = pd.Field() + normal: Axis = pd.Field(description="Normal direction of the slice.") # pylint: disable=no-member - origin: LengthType.Point = pd.Field() + origin: LengthType.Point = pd.Field(description="A single point on the slice.") class Isosurface(_OutputItemBase): - """Isosurface output item.""" + """:class:`Isosurface` class for defining an isosurface for :class:`~flow360.IsosurfaceOutput`.""" - field: Literal[IsoSurfaceFieldNames] = pd.Field() + field: Literal[IsoSurfaceFieldNames] = pd.Field( + description="Isosurface field variable. One of :code:`p`, :code:`rho`, " + + ":code:`Mach`, :code:`qcriterion`, :code:`s`, :code:`T`, :code:`Cp`, :code:`mut`, :code:`nuHat`." + ) # pylint: disable=fixme # TODO: Maybe we need some unit helper function to help user figure out what is the value to use here? iso_value: float = pd.Field(description="Expect non-dimensional value.") class Point(_PointEntityBase): - """A single point for probe output""" + """ + :class:`Point` class for defining a single point for + :class:`~flow360.ProbeOutput`/:class:`~flow360.SurfaceProbeOutput`. + """ private_attribute_entity_type_name: Literal["Point"] = pd.Field("Point", frozen=True) # pylint: disable=no-member - location: LengthType.Point = pd.Field() + location: LengthType.Point = pd.Field(description="The coordinate of the point.") class PointArray(_PointEntityBase): - """A single point for probe output""" + """ + :class:`PointArray` class for defining a line for + :class:`~flow360.ProbeOutput`/:class:`~flow360.SurfaceProbeOutput`. + """ private_attribute_entity_type_name: Literal["PointArray"] = pd.Field("PointArray", frozen=True) # pylint: disable=no-member - start: LengthType.Point = pd.Field() - end: LengthType.Point = pd.Field() - number_of_points: int = pd.Field(gt=2) + start: LengthType.Point = pd.Field(description="The starting point of the line.") + end: LengthType.Point = pd.Field(description="The end point of the line.") + number_of_points: int = pd.Field(gt=2, description="Number of points along the line.") diff --git a/flow360/component/simulation/outputs/output_fields.py b/flow360/component/simulation/outputs/output_fields.py new file mode 100644 index 000000000..78d356f61 --- /dev/null +++ b/flow360/component/simulation/outputs/output_fields.py @@ -0,0 +1,153 @@ +""" +Output field definitions +""" + +# pylint: disable=duplicate-code +from typing import List, Literal, get_args, get_origin + +# Coefficient of pressure +# Gradient of primitive solution +# k and omega +# Mach number +# Turbulent viscosity +# Turbulent viscosity and freestream dynamic viscosity ratio +# Spalart-Almaras variable +# rho, u, v, w, p (density, 3 velocities and pressure) +# Q criterion +# N-S residual +# Transition residual +# Turbulence residual +# Entropy +# N-S solution +# Transition solution +# Turbulence solution +# Temperature +# Vorticity +# Wall distance +# NumericalDissipationFactor sensor +# Heat equation residual +# Velocity with respect to non-inertial frame +# Low-Mach preconditioner factor +CommonFieldNames = Literal[ + "Cp", + "gradW", + "kOmega", + "Mach", + "mut", + "mutRatio", + "nuHat", + "primitiveVars", + "qcriterion", + "residualNavierStokes", + "residualTransition", + "residualTurbulence", + "s", + "solutionNavierStokes", + "solutionTransition", + "solutionTurbulence", + "T", + "vorticity", + "wallDistance", + "numericalDissipationFactor", + "residualHeatSolver", + "VelocityRelative", + "lowMachPreconditionerSensor", +] + +# Skin friction coefficient vector +# Magnitude of CfVec +# Non-dimensional heat flux +# Wall normals +# Spalart-Allmaras variable +# Non-dimensional wall distance +# Wall function metrics +# Surface heat transfer coefficient (static temperature as reference) +# Surface heat transfer coefficient (total temperature as reference) +SurfaceFieldNames = Literal[ + CommonFieldNames, + "CfVec", + "Cf", + "heatFlux", + "nodeNormals", + "nodeForcesPerUnitArea", + "yPlus", + "wallFunctionMetric", + "heatTransferCoefficientStaticTemperature", + "heatTransferCoefficientTotalTemperature", +] + +# BET Metrics +# BET Metrics per Disk +# Coefficient of total pressure +# Linear residual of Navier-Stokes solver +# Linear residual of turbulence solver +# Linear residual of transition solver +# DDES output for Spalart-Allmaras solver +# DDES output for kOmegaSST solver +# Local CFL number +VolumeFieldNames = Literal[ + CommonFieldNames, + "betMetrics", + "betMetricsPerDisk", + "Cpt", + "linearResidualNavierStokes", + "linearResidualTurbulence", + "linearResidualTransition", + "SpalartAllmaras_DDES", + "kOmegaSST_DDES", + "localCFL", +] + +SliceFieldNames = VolumeFieldNames + +# Pressure +# Density +# Mach number +# Q criterion +# Entropy +# Temperature +# Coefficient of pressure +# Turbulent viscosity +# Spalart-Almaras variable +IsoSurfaceFieldNames = Literal[ + "p", + "rho", + "Mach", + "qcriterion", + "s", + "T", + "Cp", + "mut", + "nuHat", +] + +AllFieldNames = Literal[CommonFieldNames, SurfaceFieldNames, VolumeFieldNames, IsoSurfaceFieldNames] + + +def _get_field_values(field_type, names): + for arg in get_args(field_type): + if get_origin(arg) is Literal: + _get_field_values(arg, names) + elif isinstance(arg, str): + names += [arg] + + +def get_field_values(field_type) -> List[str]: + """Retrieve field names from a nested literal type as list of strings""" + values = [] + _get_field_values(field_type, values) + return values + + +def _distribute_shared_output_fields(solver_values: dict, item_names: str): + if "output_fields" not in solver_values or solver_values["output_fields"] is None: + return + shared_fields = solver_values.pop("output_fields") + if solver_values[item_names] is not None: + for name in solver_values[item_names].names(): + item = solver_values[item_names][name] + for field in shared_fields: + if item.output_fields is None: + item.output_fields = [] + if field not in item.output_fields: + item.output_fields.append(field) diff --git a/flow360/component/simulation/outputs/outputs.py b/flow360/component/simulation/outputs/outputs.py index 57ea429fe..92663b8b4 100644 --- a/flow360/component/simulation/outputs/outputs.py +++ b/flow360/component/simulation/outputs/outputs.py @@ -9,12 +9,6 @@ import pydantic as pd -from flow360.component.flow360_params.flow360_fields import ( - CommonFieldNames, - SliceFieldNames, - SurfaceFieldNames, - VolumeFieldNames, -) from flow360.component.simulation.framework.base_model import Flow360BaseModel from flow360.component.simulation.framework.entity_base import EntityList from flow360.component.simulation.framework.unique_list import UniqueItemList @@ -24,6 +18,12 @@ PointArray, Slice, ) +from flow360.component.simulation.outputs.output_fields import ( + CommonFieldNames, + SliceFieldNames, + SurfaceFieldNames, + VolumeFieldNames, +) from flow360.component.simulation.primitives import GhostSurface, Surface from flow360.component.simulation.unit_system import LengthType from flow360.component.simulation.validation.validation_output import ( @@ -55,29 +55,40 @@ class _AnimationAndFileFormatSettings(_AnimationSettings): Controls how frequently the output files are generated and the file format. """ - output_format: Literal["paraview", "tecplot", "both"] = pd.Field(default="paraview") + output_format: Literal["paraview", "tecplot", "both"] = pd.Field( + default="paraview", description=":code:`paraview`, :code:`tecplot` or :code:`both`." + ) class SurfaceOutput(_AnimationAndFileFormatSettings): - """Surface output settings.""" + """:class:`SurfaceOutput` class for surface output settings.""" # pylint: disable=fixme # TODO: entities is None --> use all surfaces. This is not implemented yet. - name: Optional[str] = pd.Field(None) - entities: EntityList[Surface, GhostSurface] = pd.Field(alias="surfaces") + + name: Optional[str] = pd.Field(None, description="Name of the `SurfaceOutput`.") + entities: EntityList[Surface, GhostSurface] = pd.Field( + alias="surfaces", + description="List of output :class:`~flow360.Surface`/" + + ":class:`~flow360.GhostSurface` entities. ", + ) write_single_file: bool = pd.Field( default=False, description="Enable writing all surface outputs into a single file instead of one file per surface." + "This option currently only supports Tecplot output format." - + "Will choose the value of the last instance of this option of the same output type" - + "(SurfaceOutput or TimeAverageSurfaceOutput) in the `output` list.", + + "Will choose the value of the last instance of this option of the same output type " + + "(:class:`SurfaceOutput` or :class:`TimeAverageSurfaceOutput`) in the output list.", + ) + output_fields: UniqueItemList[SurfaceFieldNames] = pd.Field( + description="List of output variables. Including :ref:`universal output variables` " + + "and :ref:`variables specific to SurfaceOutput`. " ) - output_fields: UniqueItemList[SurfaceFieldNames] = pd.Field() output_type: Literal["SurfaceOutput"] = pd.Field("SurfaceOutput", frozen=True) class TimeAverageSurfaceOutput(SurfaceOutput): """ + :class:`TimeAverageSurfaceOutput` class for time average surface output settings. Caveats: Solver side only accept exactly the same set of output_fields (is shared) between VolumeOutput and TimeAverageVolumeOutput. @@ -89,7 +100,7 @@ class TimeAverageSurfaceOutput(SurfaceOutput): """ start_step: Union[pd.NonNegativeInt, Literal[-1]] = pd.Field( - default=-1, description="Physical time step to start calculating averaging" + default=-1, description="Physical time step to start calculating averaging." ) output_type: Literal["TimeAverageSurfaceOutput"] = pd.Field( "TimeAverageSurfaceOutput", frozen=True @@ -97,18 +108,22 @@ class TimeAverageSurfaceOutput(SurfaceOutput): class VolumeOutput(_AnimationAndFileFormatSettings): - """Volume output settings.""" + """:class:`VolumeOutput` class for volume output settings.""" - name: Optional[str] = pd.Field(None) - output_fields: UniqueItemList[VolumeFieldNames] = pd.Field() + name: Optional[str] = pd.Field(None, description="Name of the `VolumeOutput`.") + output_fields: UniqueItemList[VolumeFieldNames] = pd.Field( + description="List of output variables. Including :ref:`universal output variables`, " + + "and :ref:`variables specific to VolumeOutput`." + ) output_type: Literal["VolumeOutput"] = pd.Field("VolumeOutput", frozen=True) class TimeAverageVolumeOutput(VolumeOutput): """ + :class:`TimeAverageVolumeOutput` class for time average volume output settings. Caveats: - Solver side only accept exactly the same set of output_fields (is shared) - between VolumeOutput and TimeAverageVolumeOutput. + The solver only accepts exactly the same set of :paramref:`output_fields` (is shared) + between :class:`VolumeOutput` and :class:`TimeAverageVolumeOutput`. Also let's not worry about allowing entities here as it is not supported by solver anyway. Notes @@ -118,7 +133,7 @@ class TimeAverageVolumeOutput(VolumeOutput): """ start_step: Union[pd.NonNegativeInt, Literal[-1]] = pd.Field( - default=-1, description="Physical time step to start calculating averaging" + default=-1, description="Physical time step to start calculating averaging." ) output_type: Literal["TimeAverageVolumeOutput"] = pd.Field( "TimeAverageVolumeOutput", frozen=True @@ -126,47 +141,77 @@ class TimeAverageVolumeOutput(VolumeOutput): class SliceOutput(_AnimationAndFileFormatSettings): - """Slice output settings.""" + """:class:`SliceOutput` class for slice output settings.""" - name: Optional[str] = pd.Field(None) - entities: EntityList[Slice] = pd.Field(alias="slices") - output_fields: UniqueItemList[SliceFieldNames] = pd.Field() + name: Optional[str] = pd.Field(None, description="Name of the `SliceOutput`.") + entities: EntityList[Slice] = pd.Field( + alias="slices", + description="List of output :class:`~flow360.Slice` entities.", + ) + output_fields: UniqueItemList[SliceFieldNames] = pd.Field( + description="List of output variables. Including :ref:`universal output variables` " + + "and :ref:`variables specific to SliceOutput`. " + ) output_type: Literal["SliceOutput"] = pd.Field("SliceOutput", frozen=True) class TimeAverageSliceOutput(SliceOutput): - """TimeAverageSliceOutput output settings.""" + """:class:`TimeAverageSliceOutput` class for time average slice output settings.""" start_step: Union[pd.NonNegativeInt, Literal[-1]] = pd.Field( - default=-1, description="Physical time step to start calculating averaging" + default=-1, description="Physical time step to start calculating averaging." ) output_type: Literal["TimeAverageSliceOutput"] = pd.Field("TimeAverageSliceOutput", frozen=True) class IsosurfaceOutput(_AnimationAndFileFormatSettings): - """Isosurface output settings.""" + """:class:`IsosurfaceOutput` class for isosurface output settings.""" - name: Optional[str] = pd.Field(None) - entities: UniqueItemList[Isosurface] = pd.Field(alias="isosurfaces") - output_fields: UniqueItemList[CommonFieldNames] = pd.Field() + name: Optional[str] = pd.Field(None, description="Name of the `IsosurfaceOutput`.") + entities: UniqueItemList[Isosurface] = pd.Field( + alias="isosurfaces", + description="List of :class:`~flow360.Isosurface` entities.", + ) + output_fields: UniqueItemList[CommonFieldNames] = pd.Field( + description="List of output variables, see " + + ":ref:`universal output variables`." + ) output_type: Literal["IsosurfaceOutput"] = pd.Field("IsosurfaceOutput", frozen=True) class SurfaceIntegralOutput(Flow360BaseModel): - """Surface integral output settings.""" + """:class:`SurfaceIntegralOutput` class for surface integral output settings.""" name: str = pd.Field() - entities: EntityList[Surface, GhostSurface] = pd.Field(alias="surfaces") - output_fields: UniqueItemList[CommonFieldNames] = pd.Field() + + entities: EntityList[Surface, GhostSurface] = pd.Field( + alias="surfaces", + description="List of :class:`~flow360.component.simulation.primitives.Surface`/" + + ":class:`~flow360.component.simulation.primitives.GhostSurface` entities on which " + + "the surface integral will be calculated.", + ) + output_fields: UniqueItemList[CommonFieldNames] = pd.Field( + description="List of output variables, see " + + ":ref:`universal output variables`." + ) output_type: Literal["SurfaceIntegralOutput"] = pd.Field("SurfaceIntegralOutput", frozen=True) class ProbeOutput(Flow360BaseModel): - """Probe monitor output settings.""" - - name: str = pd.Field() - entities: EntityList[Point, PointArray] = pd.Field(alias="probe_points") - output_fields: UniqueItemList[CommonFieldNames] = pd.Field() + """:class:`ProbeOutput` class for probe monitor output settings.""" + + name: str = pd.Field(description="Name of the monitor group.") + entities: EntityList[Point, PointArray] = pd.Field( + alias="probe_points", + description="List of monitored :class:`~flow360.Point`/" + + ":class:`~flow360.PointArray` entities belonging to this " + + "monitor group. :class:`~flow360.PointArray` is used to " + + "define monitored points along a line.", + ) + output_fields: UniqueItemList[CommonFieldNames] = pd.Field( + description="List of output fields which will be added to all monitors within the monitor group," + + " see :ref:`universal output variables`." + ) output_type: Literal["ProbeOutput"] = pd.Field("ProbeOutput", frozen=True) def load_point_location_from_file(self, file_path: str): @@ -182,16 +227,28 @@ def check_unique_probe_type(cls, value): class SurfaceProbeOutput(Flow360BaseModel): """ - Probe monitor output settings. + :class:`SurfaceProbeOutput` class for surface probe monitor output settings. The monitor location will be projected to the surface closest to the point. """ - name: str = pd.Field() - entities: EntityList[Point, PointArray] = pd.Field(alias="probe_points") + name: str = pd.Field(description="Name of the surface monitor group.") + entities: EntityList[Point, PointArray] = pd.Field( + alias="probe_points", + description="List of monitored :class:`~flow360.Point`/" + + ":class:`~flow360.PointArray` entities belonging to this " + + "surface monitor group. :class:`~flow360.PointArray` " + + "is used to define monitored points along a line.", + ) # Maybe add preprocess for this and by default add all Surfaces? - target_surfaces: EntityList[Surface] = pd.Field() + target_surfaces: EntityList[Surface] = pd.Field( + description="List of :class:`~flow360.component.simulation.primitives.Surface` " + + "entities belonging to this monitor group." + ) - output_fields: UniqueItemList[SurfaceFieldNames] = pd.Field() + output_fields: UniqueItemList[SurfaceFieldNames] = pd.Field( + description="List of output variables. Including :ref:`universal output variables` " + + "and :ref:`variables specific to SurfaceOutput`. " + ) output_type: Literal["SurfaceProbeOutput"] = pd.Field("SurfaceProbeOutput", frozen=True) @pd.field_validator("entities", mode="after") @@ -206,14 +263,21 @@ class SurfaceSliceOutput(_AnimationAndFileFormatSettings): Surface slice settings. """ - name: str = pd.Field() - entities: EntityList[Slice] = pd.Field(alias="slices") + name: str = pd.Field(description="Name of the `SurfaceSliceOutput`.") + entities: EntityList[Slice] = pd.Field( + alias="slices", description="List of :class:`Slice` entities." + ) # Maybe add preprocess for this and by default add all Surfaces? - target_surfaces: EntityList[Surface] = pd.Field() + target_surfaces: EntityList[Surface] = pd.Field( + description="List of :class:`Surface` entities on which the slice will cut through." + ) output_format: Literal["paraview"] = pd.Field(default="paraview") - output_fields: UniqueItemList[SurfaceFieldNames] = pd.Field() + output_fields: UniqueItemList[SurfaceFieldNames] = pd.Field( + description="List of output variables. Including :ref:`universal output variables` " + + "and :ref:`variables specific to SurfaceOutput`. " + ) output_type: Literal["SurfaceSliceOutput"] = pd.Field("SurfaceSliceOutput", frozen=True) @pd.field_validator("entities", mode="after") @@ -250,13 +314,21 @@ class TimeAverageSurfaceProbeOutput(SurfaceProbeOutput): class AeroAcousticOutput(Flow360BaseModel): - """AeroAcoustic output settings.""" + """:class:`AeroAcousticOutput` class for aeroacoustic output settings.""" - name: Optional[str] = pd.Field(None) + name: Optional[str] = pd.Field(None, description="Name of the `AeroAcousticOutput`.") patch_type: Literal["solid"] = pd.Field("solid", frozen=True) # pylint: disable=no-member - observers: List[LengthType.Point] = pd.Field() - write_per_surface_output: bool = pd.Field(False) + observers: List[LengthType.Point] = pd.Field( + description="List of observer locations at which time history of acoustic pressure signal " + + "is stored in aeroacoustic output file. The observer locations can be outside the simulation domain, " + + "but cannot be on or inside the solid surfaces of the simulation domain." + ) + write_per_surface_output: bool = pd.Field( + False, + description="Enable writing of aeroacoustic results on a per-surface basis, " + + "in addition to results for all wall surfaces combined.", + ) output_type: Literal["AeroAcousticOutput"] = pd.Field("AeroAcousticOutput", frozen=True) diff --git a/flow360/component/simulation/primitives.py b/flow360/component/simulation/primitives.py index e937c7bd2..a64f7ca63 100644 --- a/flow360/component/simulation/primitives.py +++ b/flow360/component/simulation/primitives.py @@ -60,18 +60,32 @@ def _check_axis_is_orthogonal(axis_pair: Tuple[Axis, Axis]) -> Tuple[Axis, Axis] class ReferenceGeometry(Flow360BaseModel): """ - Contains all geometrical related refrence values - Note: - - mesh_unit is removed from here and will be a property - TODO: - - Support expression for time-dependent axis etc? - - What about force axis? + :class:`ReferenceGeometry` class contains all geometrical related refrence values. + + Example + ------- + >>> ReferenceGeometry( + ... moment_center=(1, 2, 1) * u.m, + ... moment_length=(1, 1, 1) * u.m, + ... area=1.5 * u.m**2 + ... ) + >>> ReferenceGeometry( + ... moment_center=(1, 2, 1) * u.m, + ... moment_length=1 * u.m, + ... area=1.5 * u.m**2 + ... ) # Equivalent to above """ # pylint: disable=no-member - moment_center: Optional[LengthType.Point] = pd.Field(None) - moment_length: Optional[Union[LengthType.Positive, LengthType.PositiveVector]] = pd.Field(None) - area: Optional[AreaType.Positive] = pd.Field(None) + moment_center: Optional[LengthType.Point] = pd.Field( + None, description="The x, y, z coordinate of moment center." + ) + moment_length: Optional[Union[LengthType.Positive, LengthType.PositiveVector]] = pd.Field( + None, description="The x, y, z component-wise moment reference lengths." + ) + area: Optional[AreaType.Positive] = pd.Field( + None, description="The reference area of the geometry." + ) class Transformation(Flow360BaseModel): @@ -184,10 +198,10 @@ class GenericVolume(_VolumeEntityBase): private_attribute_entity_type_name: Literal["GenericVolume"] = pd.Field( "GenericVolume", frozen=True ) - axes: Optional[OrthogonalAxes] = pd.Field(None) # Porous media support + axes: Optional[OrthogonalAxes] = pd.Field(None, description="") # Porous media support axis: Optional[Axis] = pd.Field(None) # Rotation support # pylint: disable=no-member - center: Optional[LengthType.Point] = pd.Field(None) # Rotation support + center: Optional[LengthType.Point] = pd.Field(None, description="") # Rotation support def rotation_matrix_from_axis_and_angle(axis, angle): @@ -222,7 +236,7 @@ class BoxCache(Flow360BaseModel): @final class Box(MultiConstructorBaseModel, _VolumeEntityBase): """ - Represents a box in three-dimensional space. + :class:`Box` class represents a box in three-dimensional space. """ type_name: Literal["Box"] = pd.Field("Box", frozen=True) @@ -232,8 +246,8 @@ class Box(MultiConstructorBaseModel, _VolumeEntityBase): size: LengthType.PositiveVector = pd.Field( description="The dimensions of the box (length, width, height)." ) - axis_of_rotation: Axis = pd.Field(default=(0, 0, 1)) - angle_of_rotation: AngleType = pd.Field(default=0 * u.degree) + axis_of_rotation: Axis = pd.Field(default=(0, 0, 1), description="The rotation axis.") + angle_of_rotation: AngleType = pd.Field(default=0 * u.degree, description="The rotation angle.") private_attribute_input_cache: BoxCache = pd.Field(BoxCache(), frozen=True) # pylint: disable=no-self-argument @@ -307,7 +321,7 @@ def axes(self): @final class Cylinder(_VolumeEntityBase): """ - Represents a cylinder in three-dimensional space. + :class:`Cylinder` class represents a cylinder in three-dimensional space. """ private_attribute_entity_type_name: Literal["Cylinder"] = pd.Field("Cylinder", frozen=True) @@ -332,7 +346,7 @@ def _check_inner_radius_is_less_than_outer_radius(self) -> Self: @final class Surface(_SurfaceEntityBase): """ - Represents a boudary surface in three-dimensional space. + :class:`Surface` represents a boudary surface in three-dimensional space. """ private_attribute_entity_type_name: Literal["Surface"] = pd.Field("Surface", frozen=True) diff --git a/flow360/component/simulation/time_stepping/time_stepping.py b/flow360/component/simulation/time_stepping/time_stepping.py index e01fffd2d..da06153c2 100644 --- a/flow360/component/simulation/time_stepping/time_stepping.py +++ b/flow360/component/simulation/time_stepping/time_stepping.py @@ -18,13 +18,20 @@ def _apply_default_to_none(original, default): class RampCFL(Flow360BaseModel): """ - Ramp CFL for time stepping component + :class:`RampCFL` class for the Ramp CFL setting of time stepping. """ type: Literal["ramp"] = pd.Field("ramp", frozen=True) - initial: Optional[pd.PositiveFloat] = pd.Field(None) - final: Optional[pd.PositiveFloat] = pd.Field(None) - ramp_steps: Optional[pd.PositiveInt] = pd.Field(None) + initial: Optional[pd.PositiveFloat] = pd.Field( + None, description="Initial CFL for solving pseudo time step." + ) + final: Optional[pd.PositiveFloat] = pd.Field( + None, description="Final CFL for solving pseudo time step." + ) + ramp_steps: Optional[pd.PositiveInt] = pd.Field( + None, + description="Number of pseudo steps before reaching :paramref:`RampCFL.final` within 1 physical step.", + ) @classmethod def default_unsteady(cls): @@ -43,14 +50,27 @@ def default_steady(cls): class AdaptiveCFL(Flow360BaseModel): """ - Adaptive CFL for time stepping component + :class:`AdaptiveCFL` class for Adaptive CFL setting of time stepping. """ type: Literal["adaptive"] = pd.Field("adaptive", frozen=True) - min: pd.PositiveFloat = pd.Field(default=0.1) - max: Optional[pd.PositiveFloat] = pd.Field(None) - max_relative_change: Optional[pd.PositiveFloat] = pd.Field(None) - convergence_limiting_factor: Optional[pd.PositiveFloat] = pd.Field(None) + min: pd.PositiveFloat = pd.Field( + default=0.1, description="The minimum allowable value for Adaptive CFL." + ) + max: Optional[pd.PositiveFloat] = pd.Field( + None, description="The maximum allowable value for Adaptive CFL." + ) + max_relative_change: Optional[pd.PositiveFloat] = pd.Field( + None, + description="The maximum allowable relative change of CFL (%) at each pseudo step. " + + "In unsteady simulations, the value of :paramref:`AdaptiveCFL.max_relative_change` " + + "is updated automatically depending on how well the solver converges in each physical step.", + ) + convergence_limiting_factor: Optional[pd.PositiveFloat] = pd.Field( + None, + description="This factor specifies the level of conservativeness when using Adaptive CFL. " + + "Smaller values correspond to a more conservative limitation on the value of CFL.", + ) @classmethod def default_unsteady(cls): @@ -77,14 +97,14 @@ class BaseTimeStepping(Flow360BaseModel, metaclass=ABCMeta): class Steady(BaseTimeStepping): """ - Steady time stepping component + :class:`Steady` class for specifying steady simulation. """ type_name: Literal["Steady"] = pd.Field("Steady", frozen=True) max_steps: int = pd.Field(2000, gt=0, le=100000, description="Maximum number of pseudo steps.") # pylint: disable=duplicate-code CFL: Union[RampCFL, AdaptiveCFL] = pd.Field( - default=AdaptiveCFL.default_steady(), + default=AdaptiveCFL.default_steady(), description="CFL settings." ) @pd.model_validator(mode="before") @@ -105,7 +125,7 @@ def set_default_cfl(cls, values): class Unsteady(BaseTimeStepping): """ - Unsteady time stepping component + :class:`Unsteady` class for specifying unsteady simulation. """ type_name: Literal["Unsteady"] = pd.Field("Unsteady", frozen=True) @@ -118,6 +138,7 @@ class Unsteady(BaseTimeStepping): # pylint: disable=duplicate-code CFL: Union[RampCFL, AdaptiveCFL] = pd.Field( default=AdaptiveCFL.default_unsteady(), + description="CFL settings within each physical step.", ) @pd.model_validator(mode="before") diff --git a/flow360/component/simulation/translator/utils.py b/flow360/component/simulation/translator/utils.py index 2aaf6b9da..320d92f59 100644 --- a/flow360/component/simulation/translator/utils.py +++ b/flow360/component/simulation/translator/utils.py @@ -133,7 +133,7 @@ def remove_units_in_dict(input_dict): if isinstance(value, dict) and value.keys() == unit_keys: if value["units"].startswith("flow360_") is False: raise ValueError( - f"[Internal Error] Unit {new_dict['units']} is not non-dimensionalized." + f"[Internal Error] Unit {value['units']} is not non-dimensionalized." ) new_dict[key] = value["value"] else: diff --git a/flow360/component/simulation/unit_system.py b/flow360/component/simulation/unit_system.py index e18d85b63..3c8fd0ff4 100644 --- a/flow360/component/simulation/unit_system.py +++ b/flow360/component/simulation/unit_system.py @@ -1512,7 +1512,7 @@ def __init__(self): ) conversion_system = u.UnitSystem( - "flow360", + "flow360_v2", "flow360_length_unit", "flow360_mass_unit", "flow360_time_unit", diff --git a/flow360/component/simulation/user_defined_dynamics/user_defined_dynamics.py b/flow360/component/simulation/user_defined_dynamics/user_defined_dynamics.py index 7d4187d27..fb030717f 100644 --- a/flow360/component/simulation/user_defined_dynamics/user_defined_dynamics.py +++ b/flow360/component/simulation/user_defined_dynamics/user_defined_dynamics.py @@ -11,15 +11,50 @@ class UserDefinedDynamic(Flow360BaseModel): - """:class:`UserDefinedDynamic` class""" + """:class:`UserDefinedDynamic` class for defining the user defined dynamics inputs.""" - name: str = pd.Field() - input_vars: List[str] = pd.Field() - constants: Optional[Dict[str, float]] = pd.Field(None) - output_vars: Optional[Dict[str, StringExpression]] = pd.Field(None) - state_vars_initial_value: List[StringExpression] = pd.Field() - update_law: List[StringExpression] = pd.Field() - input_boundary_patches: Optional[EntityList[Surface]] = pd.Field(None) + name: str = pd.Field(description="Name of the dynamics defined by the user.") + input_vars: List[str] = pd.Field( + description="List of the inputs to define the user defined dynamics. For example :code:`CL`, :code:`CD`, " + + ":code:`bet_NUM_torque`, :code:`bet_NUM_thrust`, (NUM is the index of the BET disk starting from 0), " + + ":code:`momentX`, :code:`momentY`, :code:`momentZ` (X/Y/Z moments with respect to :ref:`momentCenter " + + "`), :code:`forceX`, :code:`forceY`, :code:`forceZ`. For a full list of supported " + + "variable, see :ref:`here `." + ) + constants: Optional[Dict[str, float]] = pd.Field( + None, description="A list of constants that can be used in the expressions." + ) + output_vars: Optional[Dict[str, StringExpression]] = pd.Field( + None, + description="Name of the output variables and the expression for the output variables using state " + + "variables. For example :code:`alphaAngle`, :code:`betaAngle`, :code:`bet_NUM_omega` (NUM is the index " + + "of the BET disk starting from 0), :code:`theta`, :code:`omega` and :code:`omegaDot` (rotation angle/" + + "velocity/acceleration in radians for sliding interfaces). For a full list of supported variable, see " + + ":ref:`here `. Please exercise caution when choosing output " + + "variables, as any modifications to their values will be directly mirrored in the solver. Expressions " + + "follows similar guidelines as :ref:`user Defined Expressions`.", + ) + state_vars_initial_value: List[StringExpression] = pd.Field( + description="The initial value of state variables are specified here. The entries could be either values " + + "(in the form of strings, e.g., :code:`0.0`) or expression with constants defined earlier or any input " + + "and output variable. (e.g., :code:`2.0 * alphaAngle + someConstant`). The list entries correspond to " + + "the initial values for :code:`state[0]`, :code:`state[1]`, ..., respectively." + ) + update_law: List[StringExpression] = pd.Field( + "List of expressions for updating state variables. The list entries correspond to the update laws for " + + ":code:`state[0]`, :code:`state[1]`, ..., respectively. These expressions follows similar guidelines as " + + ":ref:`user Defined Expressions`." + ) + input_boundary_patches: Optional[EntityList[Surface]] = pd.Field( + None, + description="The list of :class:`~flow360.Surface` entities to which the input variables belongs. " + + "If multiple boundaries are specified then the summation over the boundaries are used as the input. " + + "For input variables that already specified the source in the name (like bet_NUM_torque) " + + "this entry does not have any effect.", + ) output_target: Optional[Cylinder] = pd.Field( - None + None, + description="The target to which the output variables belong to. For example this can be the rotating " + + "volume zone name. Only one output target is supported per user defined dynamics instance. Only " + + ":class:`~flow360.Cylinder` entity is supported as target for now.", ) # Limited to `Cylinder` for now as we have only tested using UDD to control rotation. diff --git a/flow360/component/simulation/web/asset_base.py b/flow360/component/simulation/web/asset_base.py index bfaea579f..427a64eb9 100644 --- a/flow360/component/simulation/web/asset_base.py +++ b/flow360/component/simulation/web/asset_base.py @@ -7,7 +7,7 @@ from abc import ABCMeta from typing import List, Union -from flow360.cloud.requests import LengthUnitType +from flow360.cloud.flow360_requests import LengthUnitType from flow360.cloud.rest_api import RestApi from flow360.component.interfaces import BaseInterface, ProjectInterface from flow360.component.resource_base import ( diff --git a/flow360/component/surface_mesh.py b/flow360/component/surface_mesh.py index fa6339757..41695d8ee 100644 --- a/flow360/component/surface_mesh.py +++ b/flow360/component/surface_mesh.py @@ -10,15 +10,17 @@ import pydantic.v1 as pd +from flow360.component.v1.cloud.flow360_requests import NewSurfaceMeshRequest +from flow360.component.v1.meshing.params import ( + SurfaceMeshingParams, + VolumeMeshingParams, +) from flow360.flags import Flags -from ..cloud.requests import NewSurfaceMeshRequest from ..cloud.rest_api import RestApi from ..exceptions import Flow360FileError, Flow360ValueError from ..log import log -from .flow360_params.params_base import params_generic_validator from .interfaces import SurfaceMeshInterface -from .meshing.params import SurfaceMeshingParams, VolumeMeshingParams from .resource_base import ( AssetMetaBaseModel, Flow360Resource, @@ -35,6 +37,7 @@ validate_type, zstd_compress, ) +from .v1.params_base import params_generic_validator from .validator import Validator from .volume_mesh import VolumeMeshDraft diff --git a/flow360/component/flow360_params/boundaries.py b/flow360/component/v1/boundaries.py similarity index 97% rename from flow360/component/flow360_params/boundaries.py rename to flow360/component/v1/boundaries.py index afcfb50a0..706b3dec4 100644 --- a/flow360/component/flow360_params/boundaries.py +++ b/flow360/component/v1/boundaries.py @@ -10,12 +10,11 @@ import pydantic.v1 as pd from pydantic.v1 import StrictStr -from flow360.component.flow360_params.unit_system import PressureType, VelocityType - -from ..types import Axis, Vector -from ..utils import process_expressions -from .params_base import Flow360BaseModel -from .turbulence_quantities import TurbulenceQuantitiesType +from flow360.component.types import Axis, Vector +from flow360.component.utils import process_expressions +from flow360.component.v1.params_base import Flow360BaseModel +from flow360.component.v1.turbulence_quantities import TurbulenceQuantitiesType +from flow360.component.v1.unit_system import PressureType, VelocityType BoundaryVelocityType = Union[VelocityType.Vector, Tuple[StrictStr, StrictStr, StrictStr]] BoundaryAxisType = Union[Axis, Tuple[StrictStr, StrictStr, StrictStr]] diff --git a/flow360/component/v1/cloud/flow360_requests.py b/flow360/component/v1/cloud/flow360_requests.py new file mode 100644 index 000000000..d552781e3 --- /dev/null +++ b/flow360/component/v1/cloud/flow360_requests.py @@ -0,0 +1,49 @@ +"""V1 requests for cloud component""" + +from typing import List, Optional, Union + +import pydantic.v1 as pd +from typing_extensions import Literal + +from flow360.cloud.flow360_requests import Flow360Requests +from flow360.component.v1.flow360_params import Flow360MeshParams +from flow360.flags import Flags + + +class NewVolumeMeshRequest(Flow360Requests): + """request for new volume mesh""" + + name: str = pd.Field(alias="meshName") + file_name: str = pd.Field(alias="fileName") + tags: Optional[List[str]] = pd.Field(alias="meshTags") + format: Literal["aflr3", "cgns"] = pd.Field(alias="meshFormat") + endianness: Optional[Literal["little", "big"]] = pd.Field(alias="meshEndianness") + compression: Optional[Literal["gz", "bz2", "zst"]] = pd.Field(alias="meshCompression") + mesh_params: Optional[Flow360MeshParams] = pd.Field(alias="meshParams") + solver_version: Optional[str] = pd.Field(alias="solverVersion") + if Flags.beta_features(): + version: Optional[Literal["v1", "v2"]] = pd.Field(alias="version", default="v1") + + # pylint: disable=no-self-argument + @pd.validator("mesh_params") + def set_mesh_params(cls, value: Union[Flow360MeshParams, None]): + """validate mesh params""" + if value: + return value.flow360_json() + return value + + +class NewSurfaceMeshRequest(Flow360Requests): + """request for new surface mesh""" + + name: str = pd.Field() + stem: str = pd.Field() + tags: Optional[List[str]] = pd.Field() + geometry_id: Optional[str] = pd.Field(alias="geometryId") + config: Optional[str] = pd.Field() + mesh_format: Optional[Literal["aflr3", "cgns", "stl"]] = pd.Field(alias="meshFormat") + endianness: Optional[Literal["little", "big"]] = pd.Field(alias="meshEndianness") + compression: Optional[Literal["gz", "bz2", "zst"]] = pd.Field(alias="meshCompression") + solver_version: Optional[str] = pd.Field(alias="solverVersion") + if Flags.beta_features(): + version: Optional[Literal["v1", "v2"]] = pd.Field(default="v1") diff --git a/flow360/component/flow360_params/conversions.py b/flow360/component/v1/conversions.py similarity index 98% rename from flow360/component/flow360_params/conversions.py rename to flow360/component/v1/conversions.py index 8d992e70f..756d6f321 100644 --- a/flow360/component/flow360_params/conversions.py +++ b/flow360/component/v1/conversions.py @@ -8,13 +8,12 @@ import pydantic.v1 as pd -from flow360.component.flow360_params.unit_system import ( +from flow360.component.v1.unit_system import ( flow360_conversion_unit_system, is_flow360_unit, u, ) - -from ...exceptions import Flow360ConfigurationError +from flow360.exceptions import Flow360ConfigurationError class ExtraDimensionedProperty(pd.BaseModel): @@ -135,7 +134,7 @@ def unit_converter(dimension, params, required_by: List[str] = None): ------- flow360_conversion_unit_system The conversion unit system for the specified dimension. This unit system allows for - .in_base(unit_system="flow360") conversion. + .in_base(unit_system="flow360_v1") conversion. Raises ------ diff --git a/flow360/component/flow360_params/exposed_units.py b/flow360/component/v1/exposed_units.py similarity index 100% rename from flow360/component/flow360_params/exposed_units.py rename to flow360/component/v1/exposed_units.py diff --git a/flow360/component/flow360_params/flow360_fields.py b/flow360/component/v1/flow360_fields.py similarity index 100% rename from flow360/component/flow360_params/flow360_fields.py rename to flow360/component/v1/flow360_fields.py diff --git a/flow360/component/flow360_params/flow360_legacy.py b/flow360/component/v1/flow360_legacy.py similarity index 95% rename from flow360/component/flow360_params/flow360_legacy.py rename to flow360/component/v1/flow360_legacy.py index 2b210a252..12305187a 100644 --- a/flow360/component/flow360_params/flow360_legacy.py +++ b/flow360/component/v1/flow360_legacy.py @@ -10,11 +10,8 @@ import pydantic.v1 as pd -from flow360.component.flow360_params.params_base import ( - DeprecatedAlias, - Flow360BaseModel, -) -from flow360.component.flow360_params.unit_system import DimensionedType +from flow360.component.v1.params_base import DeprecatedAlias, Flow360BaseModel +from flow360.component.v1.unit_system import DimensionedType class LegacyModel(Flow360BaseModel, metaclass=ABCMeta): diff --git a/flow360/component/flow360_params/flow360_output.py b/flow360/component/v1/flow360_output.py similarity index 98% rename from flow360/component/flow360_params/flow360_output.py rename to flow360/component/v1/flow360_output.py index 7b9c8eb32..0071acb82 100644 --- a/flow360/component/flow360_params/flow360_output.py +++ b/flow360/component/v1/flow360_output.py @@ -10,11 +10,9 @@ import pydantic.v1 as pd from pydantic.v1 import conlist -from flow360.component.flow360_params.unit_system import Flow360UnitSystem, LengthType - -from ..types import Axis, Coordinate -from ..utils import process_expressions -from .flow360_fields import ( +from flow360.component.types import Axis, Coordinate +from flow360.component.utils import process_expressions +from flow360.component.v1.flow360_fields import ( CommonFieldNames, IsoSurfaceFieldNames, SliceFieldNames, @@ -23,12 +21,13 @@ _distribute_shared_output_fields, get_field_values, ) -from .flow360_legacy import LegacyModel, get_output_fields -from .params_base import ( +from flow360.component.v1.flow360_legacy import LegacyModel, get_output_fields +from flow360.component.v1.params_base import ( Flow360BaseModel, Flow360SortableBaseModel, _self_named_property_validator, ) +from flow360.component.v1.unit_system import Flow360UnitSystem, LengthType OutputFormat = Literal[ "paraview", "tecplot", "both", "paraview,tecplot" diff --git a/flow360/component/flow360_params/flow360_params.py b/flow360/component/v1/flow360_params.py similarity index 98% rename from flow360/component/flow360_params/flow360_params.py rename to flow360/component/v1/flow360_params.py index 0ed2b5fbf..165cc2381 100644 --- a/flow360/component/flow360_params/flow360_params.py +++ b/flow360/component/v1/flow360_params.py @@ -13,40 +13,12 @@ import pydantic.v1 as pd from typing_extensions import Literal -from flow360.component.flow360_params.unit_system import ( - AngularVelocityType, - AreaType, - DensityType, - Flow360UnitSystem, - LengthType, - PressureType, - SIUnitSystem, - TemperatureType, - UnitSystem, - UnitSystemType, - VelocityType, - ViscosityType, - flow360_unit_system, - u, - unit_system_manager, -) -from flow360.flags import Flags - -from ...error_messages import unit_system_inconsistent_msg, use_unit_system_msg -from ...exceptions import ( - Flow360ConfigError, - Flow360NotImplementedError, - Flow360RuntimeError, -) -from ...log import log -from ...user_config import UserConfig -from ...version import __version__ -from ..types import Axis, Coordinate, Vector -from ..utils import convert_legacy_names, process_expressions -from . import units -from .boundaries import BoundaryType -from .conversions import ExtraDimensionedProperty -from .flow360_legacy import ( +from flow360.component.types import Axis, Coordinate, Vector +from flow360.component.utils import convert_legacy_names, process_expressions +from flow360.component.v1 import units +from flow360.component.v1.boundaries import BoundaryType +from flow360.component.v1.conversions import ExtraDimensionedProperty +from flow360.component.v1.flow360_legacy import ( FreestreamInitialConditionLegacy, LegacyModel, try_add_discriminator, @@ -54,7 +26,7 @@ try_set, try_update, ) -from .flow360_output import ( +from flow360.component.v1.flow360_output import ( AeroacousticOutput, IsoSurfaceOutput, IsoSurfaceOutputLegacy, @@ -69,22 +41,22 @@ VolumeOutput, VolumeOutputLegacy, ) -from .initial_condition import ( +from flow360.component.v1.initial_condition import ( ExpressionInitialCondition, ExpressionInitialConditionLegacy, InitialConditions, ModifiedRestartSolution, ModifiedRestartSolutionLegacy, ) -from .params_base import ( +from flow360.component.v1.params_base import ( Conflicts, Flow360BaseModel, Flow360SortableBaseModel, _self_named_property_validator, flow360_json_encoder, ) -from .physical_properties import _AirModel -from .solvers import ( +from flow360.component.v1.physical_properties import _AirModel +from flow360.component.v1.solvers import ( HeatEquationSolver, HeatEquationSolverLegacy, NavierStokesSolver, @@ -95,10 +67,34 @@ TurbulenceModelSolverLegacy, TurbulenceModelSolverType, ) -from .time_stepping import BaseTimeStepping, SteadyTimeStepping, TimeStepping -from .turbulence_quantities import TurbulenceQuantitiesType, TurbulentViscosityRatio -from .updater import updater -from .validations import ( +from flow360.component.v1.time_stepping import ( + BaseTimeStepping, + SteadyTimeStepping, + TimeStepping, +) +from flow360.component.v1.turbulence_quantities import ( + TurbulenceQuantitiesType, + TurbulentViscosityRatio, +) +from flow360.component.v1.unit_system import ( + AngularVelocityType, + AreaType, + DensityType, + Flow360UnitSystem, + LengthType, + PressureType, + SIUnitSystem, + TemperatureType, + UnitSystem, + UnitSystemType, + VelocityType, + ViscosityType, + flow360_unit_system, + u, + unit_system_manager, +) +from flow360.component.v1.updater import updater +from flow360.component.v1.validations import ( _check_aero_acoustics, _check_bet_disks_3d_coefficients_in_polars, _check_bet_disks_alphas_in_order, @@ -120,13 +116,23 @@ _check_tri_quad_boundaries, _ignore_velocity_type_in_boundaries, ) -from .volume_zones import ( +from flow360.component.v1.volume_zones import ( FluidDynamicsVolumeZone, HeatTransferVolumeZone, PorousMediumBase, ReferenceFrameType, VolumeZoneType, ) +from flow360.error_messages import unit_system_inconsistent_msg, use_unit_system_msg +from flow360.exceptions import ( + Flow360ConfigError, + Flow360NotImplementedError, + Flow360RuntimeError, +) +from flow360.flags import Flags +from flow360.log import log +from flow360.user_config import UserConfig +from flow360.version import __version__ # pylint: disable=invalid-name diff --git a/flow360/component/flow360_params/initial_condition.py b/flow360/component/v1/initial_condition.py similarity index 95% rename from flow360/component/flow360_params/initial_condition.py rename to flow360/component/v1/initial_condition.py index 4d95add02..f023e79c8 100644 --- a/flow360/component/flow360_params/initial_condition.py +++ b/flow360/component/v1/initial_condition.py @@ -9,9 +9,9 @@ import pydantic.v1 as pd from typing_extensions import Literal -from ..utils import process_expressions -from .flow360_legacy import LegacyModel -from .params_base import Flow360BaseModel +from flow360.component.utils import process_expressions +from flow360.component.v1.flow360_legacy import LegacyModel +from flow360.component.v1.params_base import Flow360BaseModel class InitialCondition(Flow360BaseModel): diff --git a/flow360/component/meshing/__init__.py b/flow360/component/v1/meshing/__init__.py similarity index 100% rename from flow360/component/meshing/__init__.py rename to flow360/component/v1/meshing/__init__.py diff --git a/flow360/component/meshing/params.py b/flow360/component/v1/meshing/params.py similarity index 98% rename from flow360/component/meshing/params.py rename to flow360/component/v1/meshing/params.py index 0de720269..43dc30505 100644 --- a/flow360/component/meshing/params.py +++ b/flow360/component/v1/meshing/params.py @@ -7,15 +7,14 @@ import pydantic.v1 as pd from typing_extensions import Literal -from flow360.flags import Flags - -from ..flow360_params.params_base import ( +from flow360.component.types import Axis, Coordinate +from flow360.component.v1.params_base import ( Flow360BaseModel, Flow360SortableBaseModel, _self_named_property_validator, flow360_json_encoder, ) -from ..types import Axis, Coordinate +from flow360.flags import Flags class Aniso(Flow360BaseModel): diff --git a/flow360/component/flow360_params/params_base.py b/flow360/component/v1/params_base.py similarity index 99% rename from flow360/component/flow360_params/params_base.py rename to flow360/component/v1/params_base.py index 3d72b6f07..0502c07b9 100644 --- a/flow360/component/flow360_params/params_base.py +++ b/flow360/component/v1/params_base.py @@ -21,16 +21,12 @@ from pydantic.v1.fields import ModelField from typing_extensions import Literal -from flow360.component.flow360_params.unit_system import ( - DimensionedType, - is_flow360_unit, -) - -from ...error_messages import do_not_modify_file_manually_msg -from ...exceptions import Flow360FileError, Flow360ValidationError -from ...log import log -from ..types import COMMENTS, TYPE_TAG_STR -from .conversions import need_conversion, require, unit_converter +from flow360.component.types import COMMENTS, TYPE_TAG_STR +from flow360.component.v1.conversions import need_conversion, require, unit_converter +from flow360.component.v1.unit_system import DimensionedType, is_flow360_unit +from flow360.error_messages import do_not_modify_file_manually_msg +from flow360.exceptions import Flow360FileError, Flow360ValidationError +from flow360.log import log def json_dumps(value, *args, **kwargs): @@ -713,7 +709,7 @@ def _convert_dimensions_to_solver( ) # pylint: disable=no-member value.units.registry = flow360_conv_system.registry - solver_values[property_name] = value.in_base(unit_system="flow360") + solver_values[property_name] = value.in_base(unit_system="flow360_v1") log.debug(f" converted to: {solver_values[property_name]}") else: solver_values[property_name] = value diff --git a/flow360/component/flow360_params/params_utils.py b/flow360/component/v1/params_utils.py similarity index 100% rename from flow360/component/flow360_params/params_utils.py rename to flow360/component/v1/params_utils.py diff --git a/flow360/component/flow360_params/physical_properties.py b/flow360/component/v1/physical_properties.py similarity index 98% rename from flow360/component/flow360_params/physical_properties.py rename to flow360/component/v1/physical_properties.py index e6a235dcb..24d5d3d03 100644 --- a/flow360/component/flow360_params/physical_properties.py +++ b/flow360/component/v1/physical_properties.py @@ -9,7 +9,7 @@ import numpy as np -from flow360.component.flow360_params.unit_system import ( +from flow360.component.v1.unit_system import ( DensityType, PressureType, TemperatureType, diff --git a/flow360/component/flow360_params/services.py b/flow360/component/v1/services.py similarity index 96% rename from flow360/component/flow360_params/services.py rename to flow360/component/v1/services.py index 3165028e5..f017a1593 100644 --- a/flow360/component/flow360_params/services.py +++ b/flow360/component/v1/services.py @@ -7,19 +7,20 @@ import pydantic.v1 as pd -from flow360.component.flow360_params.flow360_params import ( +from flow360.component.utils import remove_properties_with_prefix +from flow360.component.v1.flow360_params import ( Flow360Params, FreestreamFromVelocity, Geometry, ) -from flow360.component.flow360_params.params_base import ( +from flow360.component.v1.params_base import ( Flow360BaseModel, Flow360SortableBaseModel, _schema_optional_toggle_name, flow360_json_encoder, ) -from flow360.component.flow360_params.solvers import NavierStokesSolver, SpalartAllmaras -from flow360.component.flow360_params.unit_system import ( +from flow360.component.v1.solvers import NavierStokesSolver, SpalartAllmaras +from flow360.component.v1.unit_system import ( CGS_unit_system, SI_unit_system, UnitSystem, @@ -29,8 +30,6 @@ ) from flow360.exceptions import Flow360ConfigurationError -from ..utils import remove_properties_with_prefix - unit_system_map = { "SI": SI_unit_system, "CGS": CGS_unit_system, diff --git a/flow360/component/flow360_params/solvers.py b/flow360/component/v1/solvers.py similarity index 99% rename from flow360/component/flow360_params/solvers.py rename to flow360/component/v1/solvers.py index 5a2513b0e..f3070f0bf 100644 --- a/flow360/component/flow360_params/solvers.py +++ b/flow360/component/v1/solvers.py @@ -11,18 +11,21 @@ import pydantic.v1 as pd from typing_extensions import Literal -from flow360.flags import Flags - -from ..types import Coordinate -from .flow360_legacy import ( +from flow360.component.types import Coordinate +from flow360.component.v1.flow360_legacy import ( LegacyModel, LinearSolverLegacy, set_linear_solver_config_if_none, try_set, try_update, ) -from .params_base import Conflicts, DeprecatedAlias, Flow360BaseModel -from .time_stepping import UnsteadyTimeStepping +from flow360.component.v1.params_base import ( + Conflicts, + DeprecatedAlias, + Flow360BaseModel, +) +from flow360.component.v1.time_stepping import UnsteadyTimeStepping +from flow360.flags import Flags HEAT_EQUATION_EVAL_MAX_PER_PSEUDOSTEP_UNSTEADY = 40 HEAT_EQUATION_EVAL_FREQUENCY_STEADY = 10 diff --git a/flow360/component/flow360_params/time_stepping.py b/flow360/component/v1/time_stepping.py similarity index 97% rename from flow360/component/flow360_params/time_stepping.py rename to flow360/component/v1/time_stepping.py index 926a23223..57b7b8bb7 100644 --- a/flow360/component/flow360_params/time_stepping.py +++ b/flow360/component/v1/time_stepping.py @@ -12,9 +12,8 @@ import pydantic.v1 as pd from typing_extensions import Literal -from flow360.component.flow360_params.unit_system import TimeType - -from .params_base import DeprecatedAlias, Flow360BaseModel +from flow360.component.v1.params_base import DeprecatedAlias, Flow360BaseModel +from flow360.component.v1.unit_system import TimeType def _apply_default_to_none(original, default): diff --git a/flow360/component/flow360_params/turbulence_quantities.py b/flow360/component/v1/turbulence_quantities.py similarity index 99% rename from flow360/component/flow360_params/turbulence_quantities.py rename to flow360/component/v1/turbulence_quantities.py index 129a56308..115dfb64a 100644 --- a/flow360/component/flow360_params/turbulence_quantities.py +++ b/flow360/component/v1/turbulence_quantities.py @@ -8,7 +8,7 @@ import pydantic.v1 as pd -from .params_base import Flow360BaseModel +from flow360.component.v1.params_base import Flow360BaseModel class TurbulentKineticEnergy(Flow360BaseModel): diff --git a/flow360/component/flow360_params/unit_system.py b/flow360/component/v1/unit_system.py similarity index 99% rename from flow360/component/flow360_params/unit_system.py rename to flow360/component/v1/unit_system.py index 654e99e05..e70e4a675 100644 --- a/flow360/component/flow360_params/unit_system.py +++ b/flow360/component/v1/unit_system.py @@ -2,7 +2,8 @@ Unit system definitions and utilities """ -# pylint: disable=too-many-lines, duplicate-code +# pylint: disable=too-many-lines, duplicate-code, +# pylint: disable=missing-function-docstring from __future__ import annotations from abc import ABCMeta, abstractmethod @@ -289,7 +290,7 @@ def __modify_schema__(cls, field_schema, field): field_schema["properties"]["units"]["dimension"] = cls.dim_name # Local import to prevent exposing mappings to the user # pylint: disable=import-outside-toplevel - from flow360.component.flow360_params.exposed_units import extra_units + from flow360.component.v1.exposed_units import extra_units units = [ str(_SI_system[cls.dim_name]), @@ -1223,7 +1224,7 @@ def __init__(self): ) conversion_system = u.UnitSystem( - "flow360", + "flow360_v1", "flow360_length_unit", "flow360_mass_unit", "flow360_time_unit", diff --git a/flow360/component/flow360_params/units.py b/flow360/component/v1/units.py similarity index 95% rename from flow360/component/flow360_params/units.py rename to flow360/component/v1/units.py index 01ac4f064..12fc3d5ba 100644 --- a/flow360/component/flow360_params/units.py +++ b/flow360/component/v1/units.py @@ -5,7 +5,7 @@ import unyt from unyt import unit_symbols -from flow360.component.flow360_params.unit_system import ( +from flow360.component.v1.unit_system import ( BaseSystemType, CGS_unit_system, SI_unit_system, diff --git a/flow360/component/flow360_params/updater.py b/flow360/component/v1/updater.py similarity index 97% rename from flow360/component/flow360_params/updater.py rename to flow360/component/v1/updater.py index 0539ae948..fb682c851 100644 --- a/flow360/component/flow360_params/updater.py +++ b/flow360/component/v1/updater.py @@ -4,7 +4,7 @@ import re -from ...exceptions import Flow360NotImplementedError, Flow360RuntimeError +from flow360.exceptions import Flow360NotImplementedError, Flow360RuntimeError def _no_update(params_as_dict): diff --git a/flow360/component/flow360_params/validations.py b/flow360/component/v1/validations.py similarity index 97% rename from flow360/component/flow360_params/validations.py rename to flow360/component/v1/validations.py index 86f8a6a4c..a19738a82 100644 --- a/flow360/component/flow360_params/validations.py +++ b/flow360/component/v1/validations.py @@ -5,8 +5,7 @@ from copy import deepcopy from typing import List, Literal, Optional, Tuple, Union, get_args, get_origin -from ...log import log -from .boundaries import ( +from flow360.component.v1.boundaries import ( RotationallyPeriodic, SlipWall, SolidAdiabaticWall, @@ -14,12 +13,13 @@ TranslationallyPeriodic, WallFunction, ) -from .flow360_fields import _distribute_shared_output_fields -from .initial_condition import ExpressionInitialCondition -from .params_utils import get_all_output_fields -from .solvers import IncompressibleNavierStokesSolver -from .time_stepping import SteadyTimeStepping, UnsteadyTimeStepping -from .volume_zones import HeatTransferVolumeZone +from flow360.component.v1.flow360_fields import _distribute_shared_output_fields +from flow360.component.v1.initial_condition import ExpressionInitialCondition +from flow360.component.v1.params_utils import get_all_output_fields +from flow360.component.v1.solvers import IncompressibleNavierStokesSolver +from flow360.component.v1.time_stepping import SteadyTimeStepping, UnsteadyTimeStepping +from flow360.component.v1.volume_zones import HeatTransferVolumeZone +from flow360.log import log def _ignore_velocity_type_in_boundaries(values): diff --git a/flow360/component/flow360_params/volume_zones.py b/flow360/component/v1/volume_zones.py similarity index 97% rename from flow360/component/flow360_params/volume_zones.py rename to flow360/component/v1/volume_zones.py index 3f6605224..6cb0034e2 100644 --- a/flow360/component/flow360_params/volume_zones.py +++ b/flow360/component/v1/volume_zones.py @@ -14,7 +14,11 @@ from pydantic.v1 import StrictStr from typing_extensions import Literal -from flow360.component.flow360_params.unit_system import ( +from flow360.component.constants import NumericalConstants +from flow360.component.types import Axis, List +from flow360.component.utils import process_expressions +from flow360.component.v1.params_base import Flow360BaseModel +from flow360.component.v1.unit_system import ( AngularVelocityType, HeatSourceType, InverseAreaType, @@ -22,11 +26,6 @@ LengthType, ) -from ..constants import NumericalConstants -from ..types import Axis, List -from ..utils import process_expressions -from .params_base import Flow360BaseModel - class ReferenceFrameBase(Flow360BaseModel): """Base reference frame class""" diff --git a/flow360/component/validator.py b/flow360/component/validator.py index 4fa1a178b..57b538909 100644 --- a/flow360/component/validator.py +++ b/flow360/component/validator.py @@ -5,11 +5,15 @@ from enum import Enum from typing import Union +from flow360.component.v1.meshing.params import ( + SurfaceMeshingParams, + VolumeMeshingParams, +) + from ..cloud.rest_api import RestApi from ..exceptions import Flow360ValidationError, Flow360ValueError from ..log import log -from .flow360_params.flow360_params import Flow360Params, UnvalidatedFlow360Params -from .meshing.params import SurfaceMeshingParams, VolumeMeshingParams +from .v1.flow360_params import Flow360Params, UnvalidatedFlow360Params class Validator(Enum): diff --git a/flow360/component/volume_mesh.py b/flow360/component/volume_mesh.py index ec393efcf..b867d2547 100644 --- a/flow360/component/volume_mesh.py +++ b/flow360/component/volume_mesh.py @@ -21,16 +21,17 @@ # structure refactors import pydantic.v1 as pd -from flow360.cloud.heartbeat import post_upload_heartbeat -from flow360.cloud.requests import ( +from flow360.cloud.compress_upload import compress_and_upload_chunks +from flow360.cloud.flow360_requests import ( CopyExampleVolumeMeshRequest, LengthUnitType, - NewVolumeMeshRequest, NewVolumeMeshRequestV2, ) +from flow360.cloud.heartbeat import post_upload_heartbeat from flow360.cloud.rest_api import RestApi from flow360.cloud.s3_utils import get_local_filename_and_create_folders -from flow360.component.compress_upload import compress_and_upload_chunks +from flow360.component.v1.cloud.flow360_requests import NewVolumeMeshRequest +from flow360.component.v1.meshing.params import VolumeMeshingParams from flow360.exceptions import ( Flow360CloudFileError, Flow360FileError, @@ -43,15 +44,7 @@ from flow360.solver_version import Flow360Version from .case import Case, CaseDraft -from .flow360_params.boundaries import NoSlipWall -from .flow360_params.flow360_params import ( - Flow360MeshParams, - Flow360Params, - _GenericBoundaryWrapper, -) -from .flow360_params.params_base import params_generic_validator from .interfaces import VolumeMeshInterface, VolumeMeshInterfaceV2 -from .meshing.params import VolumeMeshingParams from .resource_base import ( AssetMetaBaseModel, AssetMetaBaseModelV2, @@ -73,6 +66,9 @@ validate_type, zstd_compress, ) +from .v1.boundaries import NoSlipWall +from .v1.flow360_params import Flow360MeshParams, Flow360Params, _GenericBoundaryWrapper +from .v1.params_base import params_generic_validator from .validator import Validator try: diff --git a/flow360/new_simulation_models.py b/flow360/new_simulation_models.py deleted file mode 100644 index b870fc535..000000000 --- a/flow360/new_simulation_models.py +++ /dev/null @@ -1,207 +0,0 @@ -""" -This module is flow360 for simulation based models -""" - -from flow360.component.simulation import services -from flow360.component.simulation import units as u -from flow360.component.simulation.entity_info import GeometryEntityInfo -from flow360.component.simulation.framework.param_utils import AssetCache -from flow360.component.simulation.meshing_param.edge_params import ( - HeightBasedRefinement, - SurfaceEdgeRefinement, -) -from flow360.component.simulation.meshing_param.face_params import SurfaceRefinement -from flow360.component.simulation.meshing_param.params import ( - MeshingDefaults, - MeshingParams, -) -from flow360.component.simulation.meshing_param.volume_params import ( - AutomatedFarfield, - AxisymmetricRefinement, - RotationCylinder, - UniformRefinement, -) -from flow360.component.simulation.models.material import Air, SolidMaterial, Sutherland -from flow360.component.simulation.models.solver_numerics import ( - HeatEquationSolver, - KOmegaSST, - KOmegaSSTModelConstants, - LinearSolver, - NavierStokesSolver, - NoneSolver, - SpalartAllmaras, - SpalartAllmarasModelConstants, - TransitionModelSolver, - TransitionModelSolverType, - TurbulenceModelSolverType, -) -from flow360.component.simulation.models.surface_models import ( - Freestream, - HeatFlux, - Inflow, - Outflow, - Periodic, - Pressure, - Rotational, - SlipWall, - SymmetryPlane, - Temperature, - TotalPressure, - Translational, - Wall, -) -from flow360.component.simulation.models.turbulence_quantities import ( - TurbulenceQuantities, -) -from flow360.component.simulation.models.volume_models import ( - ActuatorDisk, - AngleExpression, - AngularVelocity, - BETDisk, - BETDiskChord, - BETDiskSectionalPolar, - BETDiskTwist, - Fluid, - ForcePerArea, - FromUserDefinedDynamics, - HeatEquationInitialCondition, - NavierStokesInitialCondition, - PorousMedium, - Rotation, - Solid, -) -from flow360.component.simulation.operating_condition.operating_condition import ( - AerospaceCondition, - GenericReferenceCondition, - ThermalState, -) -from flow360.component.simulation.outputs.output_entities import ( - Point, - PointArray, - Slice, -) -from flow360.component.simulation.outputs.outputs import ( - AeroAcousticOutput, - IsosurfaceOutput, - ProbeOutput, - SliceOutput, - SurfaceIntegralOutput, - SurfaceOutput, - SurfaceProbeOutput, - SurfaceSliceOutput, - TimeAverageSurfaceOutput, - TimeAverageVolumeOutput, - VolumeOutput, -) -from flow360.component.simulation.primitives import ( - Box, - Cylinder, - Edge, - GenericVolume, - ReferenceGeometry, - Surface, -) -from flow360.component.simulation.simulation_params import SimulationParams -from flow360.component.simulation.time_stepping.time_stepping import ( - AdaptiveCFL, - RampCFL, - Steady, - Unsteady, -) -from flow360.component.simulation.unit_system import ( - SI_unit_system, - imperial_unit_system, -) -from flow360.component.simulation.user_defined_dynamics.user_defined_dynamics import ( - UserDefinedDynamic, -) - -__all__ = [ - "u", - "SimulationParams", - "SI_unit_system", - "imperial_unit_system", - "services", - "MeshingParams", - "MeshingDefaults", - "SurfaceRefinement", - "AutomatedFarfield", - "AxisymmetricRefinement", - "RotationCylinder", - "UniformRefinement", - "SurfaceEdgeRefinement", - "HeightBasedRefinement", - "Surface", - "Edge", - "ReferenceGeometry", - "Cylinder", - "AssetCache", - "GeometryEntityInfo", - "AerospaceCondition", - "ThermalState", - "Steady", - "Unsteady", - "RampCFL", - "AdaptiveCFL", - "Wall", - "Freestream", - "SlipWall", - "Outflow", - "Inflow", - "Periodic", - "SymmetryPlane", - "Fluid", - "Solid", - "ActuatorDisk", - "AngularVelocity", - "BETDisk", - "BETDiskChord", - "BETDiskSectionalPolar", - "BETDiskTwist", - "Rotation", - "PorousMedium", - "SurfaceOutput", - "TimeAverageSurfaceOutput", - "VolumeOutput", - "TimeAverageVolumeOutput", - "SliceOutput", - "IsosurfaceOutput", - "SurfaceIntegralOutput", - "ProbeOutput", - "SurfaceProbeOutput", - "SurfaceSliceOutput", - "AeroAcousticOutput", - "HeatEquationSolver", - "NavierStokesSolver", - "NoneSolver", - "SpalartAllmaras", - "KOmegaSST", - "SpalartAllmarasModelConstants", - "KOmegaSSTModelConstants", - "TransitionModelSolverType", - "TurbulenceModelSolverType", - "LinearSolver", - "ForcePerArea", - "Air", - "Sutherland", - "SolidMaterial", - "Slice", - "TurbulenceQuantities", - "UserDefinedDynamic", - "Translational", - "NavierStokesInitialCondition", - "FromUserDefinedDynamics", - "HeatEquationInitialCondition", - "GenericVolume", - "Temperature", - "HeatFlux", - "Point", - "PointArray", - "AngleExpression", - "Box", - "GenericReferenceCondition", - "TransitionModelSolver", - "Pressure", - "TotalPressure", - "Rotational", -] diff --git a/flow360/v1.py b/flow360/v1.py new file mode 100644 index 000000000..74d857616 --- /dev/null +++ b/flow360/v1.py @@ -0,0 +1,267 @@ +""" +Flow360 V1 (legacy) modules. +""" + +import os + +from numpy import pi + +from flow360 import global_exception_handler +from flow360.cli import flow360 +from flow360.cloud.s3_utils import ProgressCallbackInterface +from flow360.component.case import Case +from flow360.component.case import CaseList as MyCases +from flow360.component.folder import Folder +from flow360.component.surface_mesh import SurfaceMesh +from flow360.component.surface_mesh import SurfaceMeshList as MySurfaceMeshes +from flow360.component.v1 import meshing, solvers, units +from flow360.component.v1.boundaries import ( + FreestreamBoundary, + HeatFluxWall, + IsothermalWall, + MassInflow, + MassOutflow, + NoSlipWall, + PressureOutflow, + RiemannInvariant, + RotationallyPeriodic, + SlidingInterfaceBoundary, + SlipWall, + SolidAdiabaticWall, + SolidIsothermalWall, + SubsonicInflow, + SubsonicOutflowMach, + SubsonicOutflowPressure, + SupersonicInflow, + SymmetryPlane, + TranslationallyPeriodic, + VelocityInflow, + WallFunction, +) +from flow360.component.v1.flow360_output import ( + IsoSurfaceOutput, + IsoSurfaces, + MonitorOutput, + Monitors, + ProbeMonitor, + Slice, + SliceOutput, + Slices, + SurfaceIntegralMonitor, + SurfaceOutput, + Surfaces, +) +from flow360.component.v1.flow360_params import ( + ActuatorDisk, + AeroacousticOutput, + AirDensityTemperature, + AirPressureTemperature, + BETDisk, + BETDiskChord, + BETDiskSectionalPolar, + BETDiskTwist, + Boundaries, + Flow360MeshParams, + Flow360Params, + ForcePerArea, + FreestreamFromMach, + FreestreamFromMachReynolds, + FreestreamFromVelocity, + Geometry, + HeatEquationSolver, + MeshBoundary, + PorousMediumBox, + SlidingInterface, + TransitionModelSolver, + UnvalidatedFlow360Params, + UserDefinedDynamic, + VolumeOutput, + VolumeZones, + ZeroFreestream, + ZeroFreestreamFromVelocity, + air, +) +from flow360.component.v1.initial_condition import ( + ExpressionInitialCondition, + ModifiedRestartSolution, +) +from flow360.component.v1.meshing.params import ( + Aniso, + BoxRefinement, + CylinderRefinement, + Edges, + Face, + Faces, + Farfield, + ProjectAniso, + RotorDisk, + SurfaceMeshingParams, + UseAdjacent, + Volume, + VolumeMeshingParams, +) +from flow360.component.v1.solvers import ( + IncompressibleNavierStokesSolver, + KOmegaSST, + KOmegaSSTModelConstants, + LinearSolver, + NavierStokesSolver, + NoneSolver, + PressureCorrectionSolver, + SpalartAllmaras, + SpalartAllmarasModelConstants, +) +from flow360.component.v1.time_stepping import ( + AdaptiveCFL, + RampCFL, + SteadyTimeStepping, + TimeStepping, + UnsteadyTimeStepping, +) +from flow360.component.v1.turbulence_quantities import TurbulenceQuantities +from flow360.component.v1.unit_system import ( + CGS_unit_system, + SI_unit_system, + UnitSystem, + flow360_unit_system, + imperial_unit_system, +) +from flow360.component.v1.volume_zones import ( + FluidDynamicsVolumeZone, + HeatTransferVolumeZone, + InitialConditionHeatTransfer, + PorousMediumVolumeZone, + ReferenceFrame, + ReferenceFrameDynamic, + ReferenceFrameExpression, + ReferenceFrameOmegaDegrees, + ReferenceFrameOmegaRadians, +) +from flow360.component.volume_mesh import VolumeMesh +from flow360.component.volume_mesh import VolumeMeshList as MyVolumeMeshes +from flow360.flags import Flags +from flow360.user_config import UserConfig + +__all__ = [ + "ActuatorDisk", + "AdaptiveCFL", + "AeroacousticOutput", + "AirDensityTemperature", + "AirPressureTemperature", + "Aniso", + "BETDisk", + "BETDiskChord", + "BETDiskSectionalPolar", + "BETDiskTwist", + "Boundaries", + "BoxRefinement", + "CGS_unit_system", + "Case", + "CylinderRefinement", + "Edges", + "ExpressionInitialCondition", + "Face", + "Faces", + "Farfield", + "Flags", + "Flow360MeshParams", + "Flow360Params", + "FluidDynamicsVolumeZone", + "Folder", + "ForcePerArea", + "FreestreamBoundary", + "FreestreamFromMach", + "FreestreamFromMachReynolds", + "FreestreamFromVelocity", + "Geometry", + "HeatEquationSolver", + "HeatFluxWall", + "HeatTransferVolumeZone", + "IncompressibleNavierStokesSolver", + "InitialConditionHeatTransfer", + "IsoSurfaceOutput", + "IsoSurfaces", + "IsothermalWall", + "KOmegaSST", + "KOmegaSSTModelConstants", + "LinearSolver", + "MassInflow", + "MassOutflow", + "MeshBoundary", + "ModifiedRestartSolution", + "MonitorOutput", + "Monitors", + "MyCases", + "MySurfaceMeshes", + "MyVolumeMeshes", + "NavierStokesSolver", + "NoSlipWall", + "NoneSolver", + "PorousMediumBox", + "PorousMediumVolumeZone", + "PressureCorrectionSolver", + "PressureOutflow", + "ProbeMonitor", + "ProgressCallbackInterface", + "ProjectAniso", + "RampCFL", + "ReferenceFrame", + "ReferenceFrameDynamic", + "ReferenceFrameExpression", + "ReferenceFrameOmegaDegrees", + "ReferenceFrameOmegaRadians", + "RiemannInvariant", + "RotationallyPeriodic", + "RotorDisk", + "SI_unit_system", + "Slice", + "SliceOutput", + "Slices", + "SlidingInterface", + "SlidingInterfaceBoundary", + "SlipWall", + "SolidAdiabaticWall", + "SolidIsothermalWall", + "SpalartAllmaras", + "SpalartAllmarasModelConstants", + "SteadyTimeStepping", + "SubsonicInflow", + "SubsonicOutflowMach", + "SubsonicOutflowPressure", + "SupersonicInflow", + "SurfaceIntegralMonitor", + "SurfaceMesh", + "SurfaceMeshingParams", + "SurfaceOutput", + "Surfaces", + "SymmetryPlane", + "TimeStepping", + "TransitionModelSolver", + "TranslationallyPeriodic", + "TurbulenceQuantities", + "UnitSystem", + "UnsteadyTimeStepping", + "UnvalidatedFlow360Params", + "UseAdjacent", + "UserConfig", + "UserDefinedDynamic", + "VelocityInflow", + "Volume", + "VolumeMesh", + "VolumeMeshingParams", + "VolumeOutput", + "VolumeZones", + "WallFunction", + "ZeroFreestream", + "ZeroFreestreamFromVelocity", + "air", + "flow360", + "flow360_unit_system", + "global_exception_handler", + "imperial_unit_system", + "meshing", + "os", + "pi", + "solvers", + "units", +] diff --git a/poetry.lock b/poetry.lock index 31b7584e3..68082fdf1 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1,4 +1,4 @@ -# This file is automatically @generated by Poetry 1.7.1 and should not be changed by hand. +# This file is automatically @generated by Poetry 1.8.2 and should not be changed by hand. [[package]] name = "accessible-pygments" @@ -22,7 +22,7 @@ tests = ["hypothesis", "pytest"] name = "alabaster" version = "0.7.16" description = "A light, configurable Sphinx theme" -optional = true +optional = false python-versions = ">=3.9" files = [ {file = "alabaster-0.7.16-py3-none-any.whl", hash = "sha256:b46733c07dce03ae4e150330b975c75737fa60f0a7c591b6c8bf4928a28e2c92"}, @@ -1107,7 +1107,7 @@ profile = ["gprof2dot (>=2022.7.29)"] name = "docutils" version = "0.21.2" description = "Docutils -- Python Documentation Utilities" -optional = true +optional = false python-versions = ">=3.9" files = [ {file = "docutils-0.21.2-py3-none-any.whl", hash = "sha256:dafca5b9e384f0e419294eb4d2ff9fa826435bf15f15b7bd45723e8ad76811b2"}, @@ -1466,7 +1466,7 @@ all = ["flake8 (>=7.1.1)", "mypy (>=1.11.2)", "pytest (>=8.3.2)", "ruff (>=0.6.2 name = "imagesize" version = "1.4.1" description = "Getting image size from png/jpeg/jpeg2000/gif file" -optional = true +optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" files = [ {file = "imagesize-1.4.1-py2.py3-none-any.whl", hash = "sha256:0d8d18d08f840c19d0ee7ca1fd82490fdc3729b7ac93f49870406ddde8ef8d8b"}, @@ -2912,6 +2912,27 @@ files = [ {file = "numpy-1.26.0.tar.gz", hash = "sha256:f93fc78fe8bf15afe2b8d6b6499f1c73953169fad1e9a8dd086cdff3190e7fdf"}, ] +[[package]] +name = "numpydoc" +version = "1.8.0" +description = "Sphinx extension to support docstrings in Numpy format" +optional = false +python-versions = ">=3.9" +files = [ + {file = "numpydoc-1.8.0-py3-none-any.whl", hash = "sha256:72024c7fd5e17375dec3608a27c03303e8ad00c81292667955c6fea7a3ccf541"}, + {file = "numpydoc-1.8.0.tar.gz", hash = "sha256:022390ab7464a44f8737f79f8b31ce1d3cfa4b4af79ccaa1aac5e8368db587fb"}, +] + +[package.dependencies] +sphinx = ">=6" +tabulate = ">=0.8.10" +tomli = {version = ">=1.1.0", markers = "python_version < \"3.11\""} + +[package.extras] +developer = ["pre-commit (>=3.3)", "tomli"] +doc = ["intersphinx-registry", "matplotlib (>=3.5)", "numpy (>=1.22)", "pydata-sphinx-theme (>=0.13.3)", "sphinx (>=7)"] +test = ["matplotlib", "pytest", "pytest-cov"] + [[package]] name = "overrides" version = "7.7.0" @@ -4330,7 +4351,7 @@ files = [ name = "snowballstemmer" version = "2.2.0" description = "This package provides 29 stemmers for 28 languages generated from Snowball algorithms." -optional = true +optional = false python-versions = "*" files = [ {file = "snowballstemmer-2.2.0-py2.py3-none-any.whl", hash = "sha256:c8e1716e83cc398ae16824e5572ae04e0d9fc2c6b985fb0f900f5f0c96ecba1a"}, @@ -4352,7 +4373,7 @@ files = [ name = "sphinx" version = "7.4.7" description = "Python documentation generator" -optional = true +optional = false python-versions = ">=3.9" files = [ {file = "sphinx-7.4.7-py3-none-any.whl", hash = "sha256:c2419e2135d11f1951cd994d6eb18a1835bd8fdd8429f9ca375dc1f3281bd239"}, @@ -4518,6 +4539,20 @@ sphinx = ">=5" doc = ["sphinx-autoapi", "sphinx-rtd-theme", "sphinx-tabs", "sphinxemoji"] test = ["tox"] +[[package]] +name = "sphinx-paramlinks" +version = "0.6.0" +description = "Allows param links in Sphinx function/method descriptions to be linkable" +optional = true +python-versions = "*" +files = [ + {file = "sphinx-paramlinks-0.6.0.tar.gz", hash = "sha256:746a0816860aa3fff5d8d746efcbec4deead421f152687411db1d613d29f915e"}, +] + +[package.dependencies] +docutils = "*" +Sphinx = ">=4.0.0" + [[package]] name = "sphinx-prompt" version = "1.8.0" @@ -4609,7 +4644,7 @@ testing = ["coincidence (>=0.4.3)", "pygments (>=2.7.4,<=2.13.0)"] name = "sphinxcontrib-applehelp" version = "2.0.0" description = "sphinxcontrib-applehelp is a Sphinx extension which outputs Apple help books" -optional = true +optional = false python-versions = ">=3.9" files = [ {file = "sphinxcontrib_applehelp-2.0.0-py3-none-any.whl", hash = "sha256:4cd3f0ec4ac5dd9c17ec65e9ab272c9b867ea77425228e68ecf08d6b28ddbdb5"}, @@ -4625,7 +4660,7 @@ test = ["pytest"] name = "sphinxcontrib-devhelp" version = "2.0.0" description = "sphinxcontrib-devhelp is a sphinx extension which outputs Devhelp documents" -optional = true +optional = false python-versions = ">=3.9" files = [ {file = "sphinxcontrib_devhelp-2.0.0-py3-none-any.whl", hash = "sha256:aefb8b83854e4b0998877524d1029fd3e6879210422ee3780459e28a1f03a8a2"}, @@ -4641,7 +4676,7 @@ test = ["pytest"] name = "sphinxcontrib-htmlhelp" version = "2.1.0" description = "sphinxcontrib-htmlhelp is a sphinx extension which renders HTML help files" -optional = true +optional = false python-versions = ">=3.9" files = [ {file = "sphinxcontrib_htmlhelp-2.1.0-py3-none-any.whl", hash = "sha256:166759820b47002d22914d64a075ce08f4c46818e17cfc9470a9786b759b19f8"}, @@ -4657,7 +4692,7 @@ test = ["html5lib", "pytest"] name = "sphinxcontrib-jsmath" version = "1.0.1" description = "A sphinx extension which renders display math in HTML via JavaScript" -optional = true +optional = false python-versions = ">=3.5" files = [ {file = "sphinxcontrib-jsmath-1.0.1.tar.gz", hash = "sha256:a9925e4a4587247ed2191a22df5f6970656cb8ca2bd6284309578f2153e0c4b8"}, @@ -4671,7 +4706,7 @@ test = ["flake8", "mypy", "pytest"] name = "sphinxcontrib-qthelp" version = "2.0.0" description = "sphinxcontrib-qthelp is a sphinx extension which outputs QtHelp documents" -optional = true +optional = false python-versions = ">=3.9" files = [ {file = "sphinxcontrib_qthelp-2.0.0-py3-none-any.whl", hash = "sha256:b18a828cdba941ccd6ee8445dbe72ffa3ef8cbe7505d8cd1fa0d42d3f2d5f3eb"}, @@ -4687,7 +4722,7 @@ test = ["defusedxml (>=0.7.1)", "pytest"] name = "sphinxcontrib-serializinghtml" version = "2.0.0" description = "sphinxcontrib-serializinghtml is a sphinx extension which outputs \"serialized\" HTML files (json and pickle)" -optional = true +optional = false python-versions = ">=3.9" files = [ {file = "sphinxcontrib_serializinghtml-2.0.0-py3-none-any.whl", hash = "sha256:6e2cb0eef194e10c27ec0023bfeb25badbbb5868244cf5bc5bdc04e4464bf331"}, @@ -4770,7 +4805,7 @@ dev = ["hypothesis (>=6.70.0)", "pytest (>=7.1.0)"] name = "tabulate" version = "0.9.0" description = "Pretty-print tabular data" -optional = true +optional = false python-versions = ">=3.7" files = [ {file = "tabulate-0.9.0-py3-none-any.whl", hash = "sha256:024ca478df22e9340661486f85298cff5f6dcdba14f3813e8830015b9ed1948f"}, @@ -5124,9 +5159,9 @@ cffi = {version = ">=1.11", markers = "platform_python_implementation == \"PyPy\ cffi = ["cffi (>=1.11)"] [extras] -docs = ["autodoc_pydantic", "cairosvg", "ipython", "jinja2", "jupyter", "myst-parser", "nbconvert", "nbdime", "nbsphinx", "pydata-sphinx-theme", "readthedocs-sphinx-search", "sphinx", "sphinx-book-theme", "sphinx-copybutton", "sphinx-favicon", "sphinx-notfound-page", "sphinx-prompt", "sphinx-sitemap", "sphinx-tabs", "sphinx_design", "sphinx_toolbox", "sphinxcontrib-svg2pdfconverter", "sphinxemoji"] +docs = ["autodoc_pydantic", "cairosvg", "ipython", "jinja2", "jupyter", "myst-parser", "nbconvert", "nbdime", "nbsphinx", "numpydoc", "pydata-sphinx-theme", "readthedocs-sphinx-search", "sphinx", "sphinx-book-theme", "sphinx-copybutton", "sphinx-favicon", "sphinx-notfound-page", "sphinx-prompt", "sphinx-sitemap", "sphinx-tabs", "sphinx_design", "sphinx_paramlinks", "sphinx_toolbox", "sphinxcontrib-svg2pdfconverter", "sphinxemoji"] [metadata] lock-version = "2.0" python-versions = ">=3.9,<3.12" -content-hash = "68e2b0a819ba27869350047433031ea97ab479abe517f1bbbb2d60498b71e6aa" +content-hash = "f98d5ccabd7699df12cdbcda67892f6707f774e22d3680ac424e94f9a40582bd" diff --git a/pyproject.toml b/pyproject.toml index 6d1ed1e63..7a548e470 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -59,6 +59,8 @@ sphinxcontrib-svg2pdfconverter = {version="*", optional = true} sphinx-prompt = {version="*", optional = true} sphinx_design = {version="*", optional = true} sphinx_toolbox = {version="*", optional = true} +sphinx_paramlinks = {version="*", optional = true} +numpydoc = "^1.8.0" [tool.poetry.group.dev.dependencies] @@ -99,6 +101,8 @@ docs = [ "sphinx-prompt", "sphinx_design", "sphinx_toolbox", + "sphinx_paramlinks", + "numpydoc" ] [tool.isort] diff --git a/tests/data/geometry/cylinder.x_t b/tests/data/geometry/cylinder.x_t deleted file mode 100644 index 7e4a7dfa5..000000000 --- a/tests/data/geometry/cylinder.x_t +++ /dev/null @@ -1,66 +0,0 @@ -**ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz************************** -**PARASOLID !"#$%&'()*+,-./:;<=>?@[\]^_`{|}~0123456789************************** -**PART1; -MC=AMD64; -MC_MODEL=AMD64 Family 25 Model 8 Stepping 2, AuthenticAMD; -MC_ID=unknown; -OS=Windows_NT; -OS_RELEASE=unknown; -FRU=Parasolid Version 35.1, build 251, 11- 4-2023; -APPL=SOLIDWORKS 2024-2024016; -SITE=; -USER=unknown; -FORMAT=text; -GUISE=transmit; -KEY=cylinder_v2; -FILE=cylinder_v2.x_t; -DATE=Fri May 17 11:19:49 2024; -**PART2; -SCH=SCH_3501251_35102; -USFLD_SIZE=0; -**PART3; -**END_OF_HEADER***************************************************************** -T51 : TRANSMIT FILE created by modeller version 350125123 SCH_3501251_35102_1300 -6231 0 12 36 CCCI7 lattice222 0 CCCI4 mesh1006 0 I8 polyline1008 0 CCCCCCCDI5 ow -ner1040 0 CCCI16 boundary_lattice222 0 CCCI13 boundary_mesh1006 0 I17 boundary_p -olyline1008 0 CCCA16 index_map_offset0 0 1 dA9 index_map82 0 A17 node_id_index_m -ap82 0 A20 schema_embedding_map82 0 A5 child12 0 A14 lowest_node_id0 0 1 dA16 me -sh_offset_data206 0 Z1 102 2 3 0 0 0 0 0 0 0 1e3 1e-8 0 4 0 1 0 1 1 5 0 6 7 0 0 - 0 8 9 0 0 0 0 0 0 0 0 81 255 2 2 96 10 1 11 0 0 0 0 12 70 11 CI9 list_type0 0 1 - uI10 notransmit0 0 1 lCCCDCCDI12 finger_index0 0 1 dI12 finger_block1012 0 CZ3 - 0 4 T1 0 0 11 20 1 13 13 13 255 5 31 0 1 0 14 0 0 15 0 51 255 6 30 0 14 16 0 0 - -0 0 .01760714246861955 0 0 -1 .01 -1 0 0 31 255 7 25 0 17 18 0 0 +0 0 0 0 0 1 - 1 0 0 .01 19 9 CCCCCCI5 frame230 0 CA5 owner12 0 Z8 9 0 1 15 0 19 0 V0 16 255 9 - 5 0 ?20 0 17 18 0 0 1 17 255 20 0 21 20 20 0 22 9 0 0 +16 17 20 0 ?23 9 0 7 0 0 - 1 31 18 7 0 9 0 7 0 +0 0 .01760714246861955 0 0 1 1 0 0 .01 17 23 0 24 23 23 0 - 25 17 0 0 +15 255 24 28 0 23 14 0 17 25 0 26 25 25 0 23 17 0 0 -15 26 19 0 25 2 -7 0 14 255 27 18 28 ?0 29 26 5 16 -0 0 0 29 19 81 1 28 98 30 27 31 0 0 32 33 14 - 29 1 32 ?27 14 21 5 34 +0 0 27 14 19 50 255 16 24 0 27 34 6 0 +0 0 0 0 0 1 1 0 - 0 13 19 10 0 0 0 0 0 0 8 14 14 14 27 35 ?29 0 36 5 6 -0 0 29 0 19 81 1 35 102 3 -0 14 37 0 32 0 38 15 36 26 0 22 14 24 17 22 0 36 22 22 0 20 9 0 0 -80 7 CCCCCDI1 -2 legal_owners0 16 1 lCZ1 30 39 40 9000 1 1 1 1 1 1 1 1 0 FFFFTFTFFFFFFFFF1 81 3 - 37 101 41 14 42 35 43 0 44 0 0 81 1 32 100 30 29 43 0 28 35 45 82 255 1 38 -946 -798438 81 3 43 99 41 29 46 32 31 37 47 0 0 82 1 45 -948764518 80 3 41 48 49 9000 - 0 0 0 0 3 5 0 0 0 FFFFTFFFFFFFFFFF1 1 1 81 1 46 84 50 29 0 43 42 51 52 81 3 31 - 97 41 27 51 28 0 43 53 0 0 82 6 47 0 -719274033 31107179 0 0 0 81 1 51 85 50 27 - 0 31 46 0 54 82 6 53 0 -719274033 31107179 0 0 0 80 1 50 0 55 8001 0 0 0 0 3 5 - 0 0 0 FFFFTFTFFFFFFFFF2 83 255 3 54 .792156862745098 .819607843137255 .93333333 -3333333 79 255 15 55 SDL/TYSA_COLOUR81 1 42 83 50 14 0 37 0 46 56 83 3 52 .79215 -6862745098 .819607843137255 .933333333333333 83 3 56 .792156862745098 .819607843 -137255 .933333333333333 79 18 49 DOWNSTREAM_FACE_ID82 6 44 0 -719274033 31107179 - 0 0 0 79 14 40 SWEntUnchanged50 34 3 0 29 0 16 0 +0 0 .01760714246861955 0 0 1 - 1 0 0 15 21 4 0 20 29 0 82 1 33 -947060582 19 15 32 0 1 0 8 5 0 S0 74 4 CI16 in -dex_map_offset0 0 1 dCCZ20 13 11 0 0 37 57 58 59 35 60 61 62 11 51 2 0 0 0 0 0 0 - 0 0 0 81 2 57 50 63 1 0 58 0 0 0 64 81 2 58 53 65 1 57 59 0 0 0 66 81 2 59 54 6 -7 1 58 60 0 0 68 0 81 1 60 58 69 1 59 61 0 0 70 81 2 61 64 71 1 60 62 0 0 72 0 8 -1 2 62 68 73 1 61 11 0 0 0 74 81 2 11 74 75 1 62 2 0 0 0 0 80 2 75 76 77 9000 0 - 0 0 0 3 5 0 0 0 FFTFFFFFFFFFFFFF9 1 79 16 77 BODY_RECIPE_200180 2 73 78 79 9000 - 0 0 0 0 3 5 0 0 0 FFTFFFFFFFFFFFFF9 1 82 1 74 1 79 24 79 BODY_IN_LIGHTWEIGHT_PE -RM80 2 71 80 81 8004 0 0 0 0 3 5 0 0 0 FFTFFFFFFFFFFFFF2 3 83 1 72 1 79 16 81 SD -L/TYSA_DENSITY80 1 69 82 83 9000 1 1 1 1 1 1 1 1 0 FFTFFFFFFFFFFFFF1 82 1 70 510 -57 79 10 83 BODY_MATCH80 2 67 84 85 9000 0 0 0 0 3 5 0 0 0 FFTFTTTFFTFFFFFF10 10 - 98 255 13 68 66 111 115 115 45 69 120 116 114 117 100 101 49 79 23 85 SWIMPLICI -TBODYNAME_ID_U80 2 65 86 87 9000 0 0 0 0 3 5 0 0 0 FFTFFFFFFFFFFFFF9 1 82 1 66 3 -3 79 30 87 LAST_BODY_MODIFYING_FEATURE_ID80 2 63 88 89 9000 0 0 0 0 3 5 0 0 0 FF -TFFFFFFFFFFFFF9 1 82 1 64 151 79 19 89 ENT_TIME_STAMP_200180 2 10 90 91 9000 0 0 - 0 0 3 5 0 0 0 FFTFFFFFFFFFFFFF9 1 82 1 12 101 79 12 91 ATOM_ID_20011 0 diff --git a/tests/om6wing/Flow360Mesh.json b/tests/om6wing/Flow360Mesh.json deleted file mode 100644 index cb2ccac2a..000000000 --- a/tests/om6wing/Flow360Mesh.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "boundaries" : - { - "noSlipWalls" : [1] - } -} diff --git a/tests/simulation/conftest.py b/tests/simulation/conftest.py index 5239c0b14..917ec8e52 100644 --- a/tests/simulation/conftest.py +++ b/tests/simulation/conftest.py @@ -1,5 +1,10 @@ from abc import ABCMeta +import numpy as np +import pytest +import unyt + +from flow360.component.simulation import unit_system from flow360.component.simulation.framework.entity_base import EntityBase from flow360.component.simulation.framework.entity_registry import EntityRegistry @@ -23,3 +28,71 @@ def __getitem__(self, key: str) -> list[EntityBase]: return found_entities[0] return found_entities + + +@pytest.fixture() +def array_equality_override(): + # Save original methods + original_unyt_eq = unyt.unyt_array.__eq__ + original_unyt_ne = unyt.unyt_array.__ne__ + original_flow360_eq = unit_system._Flow360BaseUnit.__eq__ + original_flow360_ne = unit_system._Flow360BaseUnit.__ne__ + + # Overload equality for unyt arrays + def unyt_array_eq(self: unyt.unyt_array, other: unyt.unyt_array): + if isinstance(other, unit_system._Flow360BaseUnit): + return flow360_unit_array_eq(other, self) + if isinstance(self, unyt.unyt_quantity): + return np.ndarray.__eq__(self, other) + elif self.size == other.size: + return all(self[i] == other[i] for i in range(len(self))) + return False + + def unyt_array_ne(self: unyt.unyt_array, other: unyt.unyt_array): + if isinstance(other, unit_system._Flow360BaseUnit): + return flow360_unit_array_ne(other, self) + if isinstance(self, unyt.unyt_quantity): + return np.ndarray.__ne__(self, other) + elif self.size == other.size: + return any(self[i] != other[i] for i in range(len(self))) + return True + + def flow360_unit_array_eq( + self: unit_system._Flow360BaseUnit, other: unit_system._Flow360BaseUnit + ): + if isinstance(other, (unit_system._Flow360BaseUnit, unyt.unyt_array)): + if self.size == other.size: + if str(self.units) == str(other.units): + if self.size == 1: + return np.ndarray.__eq__(self.v, other.v) + if isinstance(other, unyt.unyt_array): + other = unit_system._Flow360BaseUnit.factory(other.v, str(other.units)) + return all(np.ndarray.__eq__(v.v, o.v) for v, o in zip(self, other)) + return False + + def flow360_unit_array_ne( + self: unit_system._Flow360BaseUnit, other: unit_system._Flow360BaseUnit + ): + if isinstance(other, (unit_system._Flow360BaseUnit, unyt.unyt_array)): + if self.size == other.size: + if str(self.units) == str(other.units): + if self.size == 1: + return np.ndarray.__ne__(self.v, other.v) + if isinstance(other, unyt.unyt_array): + other = unit_system._Flow360BaseUnit.factory(other.v, str(other.units)) + return any(np.ndarray.__ne__(v.v, o.v) for v, o in zip(self, other)) + return True + + unyt.unyt_array.__eq__ = unyt_array_eq + unyt.unyt_array.__ne__ = unyt_array_ne + unit_system._Flow360BaseUnit.__eq__ = flow360_unit_array_eq + unit_system._Flow360BaseUnit.__ne__ = flow360_unit_array_ne + + # Yield control to the test + yield + + # Restore original methods + unyt.unyt_array.__eq__ = original_unyt_eq + unyt.unyt_array.__ne__ = original_unyt_ne + unit_system._Flow360BaseUnit.__eq__ = original_flow360_eq + unit_system._Flow360BaseUnit.__ne__ = original_flow360_ne diff --git a/tests/simulation/framework/test_base_model_v2.py b/tests/simulation/framework/test_base_model_v2.py index 48d1f8044..e15237cdf 100644 --- a/tests/simulation/framework/test_base_model_v2.py +++ b/tests/simulation/framework/test_base_model_v2.py @@ -7,7 +7,6 @@ import yaml import flow360.component.simulation.units as u -from flow360.component.flow360_params.flow360_params import Flow360BaseModel from flow360.component.simulation.framework.base_model import Flow360BaseModel from flow360.log import set_logging_level diff --git a/tests/simulation/framework/test_context_validators.py b/tests/simulation/framework/test_context_validators.py index 988d3416b..b99364462 100644 --- a/tests/simulation/framework/test_context_validators.py +++ b/tests/simulation/framework/test_context_validators.py @@ -3,7 +3,6 @@ import pydantic as pd import flow360.component.simulation.units as u -from flow360.component.flow360_params.flow360_params import Flow360BaseModel from flow360.component.simulation.framework.base_model import Flow360BaseModel from flow360.component.simulation.validation import validation_context from flow360.log import set_logging_level diff --git a/tests/simulation/framework/test_unique_list.py b/tests/simulation/framework/test_unique_list.py index 2f6ebf4df..e27ead3c3 100644 --- a/tests/simulation/framework/test_unique_list.py +++ b/tests/simulation/framework/test_unique_list.py @@ -4,12 +4,12 @@ import pydantic as pd import pytest -from flow360.component.flow360_params.flow360_fields import CommonFieldNames from flow360.component.simulation.framework.base_model import Flow360BaseModel from flow360.component.simulation.framework.unique_list import ( UniqueItemList, UniqueStringList, ) +from flow360.component.simulation.outputs.output_fields import CommonFieldNames from flow360.component.simulation.primitives import Surface, SurfacePair diff --git a/tests/test_flow360.py b/tests/test_current_flow360_version.py similarity index 59% rename from tests/test_flow360.py rename to tests/test_current_flow360_version.py index 17fd69823..93bf5c471 100644 --- a/tests/test_flow360.py +++ b/tests/test_current_flow360_version.py @@ -1,4 +1,4 @@ -from flow360 import __version__ +from flow360.version import __version__ def test_version(): diff --git a/tests/test_results.py b/tests/test_results.py index 9edf80eff..a2a22c243 100644 --- a/tests/test_results.py +++ b/tests/test_results.py @@ -6,8 +6,8 @@ import pandas import pytest -import flow360 as fl -import flow360.component.flow360_params.units as u1 +import flow360.component.v1.units as u1 +import flow360.v1 as fl from flow360 import log from flow360.component.simulation import units as u2 from flow360.component.simulation.operating_condition.operating_condition import ( diff --git a/tests/test_shared_accounts.py b/tests/test_shared_accounts.py index c242392a1..14ab1921a 100644 --- a/tests/test_shared_accounts.py +++ b/tests/test_shared_accounts.py @@ -2,7 +2,8 @@ import pytest -from flow360 import Accounts, Env +from flow360.accounts_utils import Accounts +from flow360.environment import Env def test_shared_account(mock_response, monkeypatch): diff --git a/tests/test_utils.py b/tests/test_utils.py index 6816047fe..02febaa65 100644 --- a/tests/test_utils.py +++ b/tests/test_utils.py @@ -2,7 +2,7 @@ import pytest -from flow360 import Accounts +from flow360.accounts_utils import Accounts from flow360.cli.dict_utils import merge_overwrite from flow360.component.utils import ( CompressionFormat, diff --git a/tests/test_version.py b/tests/test_version_comparisons.py similarity index 100% rename from tests/test_version.py rename to tests/test_version_comparisons.py diff --git a/tests/utils.py b/tests/utils.py index 7fc68d7d7..4ebee8c38 100644 --- a/tests/utils.py +++ b/tests/utils.py @@ -15,7 +15,6 @@ S3TransferType, get_local_filename_and_create_folders, ) -from flow360.component.flow360_params import unit_system @pytest.fixture @@ -147,74 +146,6 @@ def compare_to_ref(obj, ref_path, content_only=False): @pytest.fixture() -def array_equality_override(): - # Save original methods - original_unyt_eq = unyt.unyt_array.__eq__ - original_unyt_ne = unyt.unyt_array.__ne__ - original_flow360_eq = unit_system._Flow360BaseUnit.__eq__ - original_flow360_ne = unit_system._Flow360BaseUnit.__ne__ - - # Overload equality for unyt arrays - def unyt_array_eq(self: unyt.unyt_array, other: unyt.unyt_array): - if isinstance(other, unit_system._Flow360BaseUnit): - return flow360_unit_array_eq(other, self) - if isinstance(self, unyt.unyt_quantity): - return np.ndarray.__eq__(self, other) - elif self.size == other.size: - return all(self[i] == other[i] for i in range(len(self))) - return False - - def unyt_array_ne(self: unyt.unyt_array, other: unyt.unyt_array): - if isinstance(other, unit_system._Flow360BaseUnit): - return flow360_unit_array_ne(other, self) - if isinstance(self, unyt.unyt_quantity): - return np.ndarray.__ne__(self, other) - elif self.size == other.size: - return any(self[i] != other[i] for i in range(len(self))) - return True - - def flow360_unit_array_eq( - self: unit_system._Flow360BaseUnit, other: unit_system._Flow360BaseUnit - ): - if isinstance(other, (unit_system._Flow360BaseUnit, unyt.unyt_array)): - if self.size == other.size: - if str(self.units) == str(other.units): - if self.size == 1: - return np.ndarray.__eq__(self.v, other.v) - if isinstance(other, unyt.unyt_array): - other = unit_system._Flow360BaseUnit.factory(other.v, str(other.units)) - return all(np.ndarray.__eq__(v.v, o.v) for v, o in zip(self, other)) - return False - - def flow360_unit_array_ne( - self: unit_system._Flow360BaseUnit, other: unit_system._Flow360BaseUnit - ): - if isinstance(other, (unit_system._Flow360BaseUnit, unyt.unyt_array)): - if self.size == other.size: - if str(self.units) == str(other.units): - if self.size == 1: - return np.ndarray.__ne__(self.v, other.v) - if isinstance(other, unyt.unyt_array): - other = unit_system._Flow360BaseUnit.factory(other.v, str(other.units)) - return any(np.ndarray.__ne__(v.v, o.v) for v, o in zip(self, other)) - return True - - unyt.unyt_array.__eq__ = unyt_array_eq - unyt.unyt_array.__ne__ = unyt_array_ne - unit_system._Flow360BaseUnit.__eq__ = flow360_unit_array_eq - unit_system._Flow360BaseUnit.__ne__ = flow360_unit_array_ne - - # Yield control to the test - yield - - # Restore original methods - unyt.unyt_array.__eq__ = original_unyt_eq - unyt.unyt_array.__ne__ = original_unyt_ne - unit_system._Flow360BaseUnit.__eq__ = original_flow360_eq - unit_system._Flow360BaseUnit.__ne__ = original_flow360_ne - - -@pytest.fixture def s3_download_override(monkeypatch): def s3_mock_download( resource_id: str, diff --git a/flow360/component/flow360_params/__init__.py b/tests/v1/__init__.py similarity index 100% rename from flow360/component/flow360_params/__init__.py rename to tests/v1/__init__.py diff --git a/tests/_test_case.py b/tests/v1/_test_case.py similarity index 88% rename from tests/_test_case.py rename to tests/v1/_test_case.py index 921674bb0..7319d80a9 100644 --- a/tests/_test_case.py +++ b/tests/v1/_test_case.py @@ -1,9 +1,6 @@ -from flow360 import Env from flow360.component.case import Case -from flow360.component.flow360_params.flow360_params import ( - Flow360Params, - UnsteadyTimeStepping, -) +from flow360.component.v1.flow360_params import Flow360Params, UnsteadyTimeStepping +from flow360.v1 import Env def test_from_cloud(): diff --git a/tests/_test_case_submit_solver_version.py b/tests/v1/_test_case_submit_solver_version.py similarity index 99% rename from tests/_test_case_submit_solver_version.py rename to tests/v1/_test_case_submit_solver_version.py index 989bb6b60..9094fd1c7 100644 --- a/tests/_test_case_submit_solver_version.py +++ b/tests/v1/_test_case_submit_solver_version.py @@ -1,6 +1,6 @@ import pytest -import flow360 as fl +import flow360.v1 as fl from flow360.examples import OM6wing from flow360.exceptions import Flow360RuntimeError, Flow360ValidationError from flow360.log import set_logging_level diff --git a/tests/_test_cli.py b/tests/v1/_test_cli.py similarity index 100% rename from tests/_test_cli.py rename to tests/v1/_test_cli.py diff --git a/tests/v1/_test_cli_tmp.py b/tests/v1/_test_cli_tmp.py new file mode 100644 index 000000000..a8c62e1da --- /dev/null +++ b/tests/v1/_test_cli_tmp.py @@ -0,0 +1,62 @@ +import os.path +import shutil +from os.path import expanduser + +import pytest +import toml +from click.testing import CliRunner + +home = expanduser("~") + + +@pytest.fixture +def backup_and_restore_file(): + original_file = f"{home}/.flow360/config.toml" + backup_file = f"{home}/.flow360/config.toml.bak" + + # Backup the original file + if os.path.exists(original_file): + shutil.copy2(original_file, backup_file) + print(f"Backup of {original_file} created as {backup_file}") + + yield # This allows the test to run + + # Restore the original file after the test + if os.path.exists(backup_file): + shutil.copy2(backup_file, original_file) + os.remove(backup_file) + print(f"{original_file} restored from backup") + + +# @pytest.fixture(backup_and_restore_file) +def test_no_configure(backup_and_restore_file): + if os.path.exists(f"{home}/.flow360/config.toml"): + print("Deleting existing config file") + os.remove(f"{home}/.flow360/config.toml") + assert not os.path.exists(f"{home}/.flow360/config.toml") + + runner = CliRunner() + + from flow360.cli import flow360 + + result = runner.invoke(flow360, ["configure"], input="apikey") + assert result.exit_code == 0 + assert result.output == "API Key: apikey\ndone.\n" + print(">>> result.output", result.output) + with open(f"{home}/.flow360/config.toml") as f: + config = toml.loads(f.read()) + print(">>> config", config) + assert config.get("default", {}).get("apikey", "") == "apikey" + + +# @pytest.fixture(backup_and_restore_file) +def test_with_existing_configure(backup_and_restore_file): + runner = CliRunner() + from flow360.cli import flow360 + + result = runner.invoke(flow360, ["configure"], input="apikey") + assert result.exit_code == 0 + assert result.output == "API Key[apikey]: apikey\ndone.\n" + with open(f"{home}/.flow360/config.toml") as f: + config = toml.loads(f.read()) + assert config.get("default", {}).get("apikey", "") == "apikey" diff --git a/tests/_test_http.py b/tests/v1/_test_http.py similarity index 100% rename from tests/_test_http.py rename to tests/v1/_test_http.py diff --git a/tests/_test_validate.py b/tests/v1/_test_validate.py similarity index 97% rename from tests/_test_validate.py rename to tests/v1/_test_validate.py index e1e35e12b..bb9503b14 100644 --- a/tests/_test_validate.py +++ b/tests/v1/_test_validate.py @@ -2,7 +2,7 @@ import pytest -import flow360 as fl +import flow360.v1 as fl from flow360.component.validator import Validator assertions = unittest.TestCase("__init__") diff --git a/tests/v1/conftest.py b/tests/v1/conftest.py new file mode 100644 index 000000000..ed5a6693e --- /dev/null +++ b/tests/v1/conftest.py @@ -0,0 +1,73 @@ +import numpy as np +import pytest +import unyt + +from flow360.component.v1 import unit_system + + +@pytest.fixture() +def array_equality_override(): + # Save original methods + original_unyt_eq = unyt.unyt_array.__eq__ + original_unyt_ne = unyt.unyt_array.__ne__ + original_flow360_eq = unit_system._Flow360BaseUnit.__eq__ + original_flow360_ne = unit_system._Flow360BaseUnit.__ne__ + + # Overload equality for unyt arrays + def unyt_array_eq(self: unyt.unyt_array, other: unyt.unyt_array): + if isinstance(other, unit_system._Flow360BaseUnit): + return flow360_unit_array_eq(other, self) + if isinstance(self, unyt.unyt_quantity): + return np.ndarray.__eq__(self, other) + elif self.size == other.size: + return all(self[i] == other[i] for i in range(len(self))) + return False + + def unyt_array_ne(self: unyt.unyt_array, other: unyt.unyt_array): + if isinstance(other, unit_system._Flow360BaseUnit): + return flow360_unit_array_ne(other, self) + if isinstance(self, unyt.unyt_quantity): + return np.ndarray.__ne__(self, other) + elif self.size == other.size: + return any(self[i] != other[i] for i in range(len(self))) + return True + + def flow360_unit_array_eq( + self: unit_system._Flow360BaseUnit, other: unit_system._Flow360BaseUnit + ): + if isinstance(other, (unit_system._Flow360BaseUnit, unyt.unyt_array)): + if self.size == other.size: + if str(self.units) == str(other.units): + if self.size == 1: + return np.ndarray.__eq__(self.v, other.v) + if isinstance(other, unyt.unyt_array): + other = unit_system._Flow360BaseUnit.factory(other.v, str(other.units)) + return all(np.ndarray.__eq__(v.v, o.v) for v, o in zip(self, other)) + return False + + def flow360_unit_array_ne( + self: unit_system._Flow360BaseUnit, other: unit_system._Flow360BaseUnit + ): + if isinstance(other, (unit_system._Flow360BaseUnit, unyt.unyt_array)): + if self.size == other.size: + if str(self.units) == str(other.units): + if self.size == 1: + return np.ndarray.__ne__(self.v, other.v) + if isinstance(other, unyt.unyt_array): + other = unit_system._Flow360BaseUnit.factory(other.v, str(other.units)) + return any(np.ndarray.__ne__(v.v, o.v) for v, o in zip(self, other)) + return True + + unyt.unyt_array.__eq__ = unyt_array_eq + unyt.unyt_array.__ne__ = unyt_array_ne + unit_system._Flow360BaseUnit.__eq__ = flow360_unit_array_eq + unit_system._Flow360BaseUnit.__ne__ = flow360_unit_array_ne + + # Yield control to the test + yield + + # Restore original methods + unyt.unyt_array.__eq__ = original_unyt_eq + unyt.unyt_array.__ne__ = original_unyt_ne + unit_system._Flow360BaseUnit.__eq__ = original_flow360_eq + unit_system._Flow360BaseUnit.__ne__ = original_flow360_ne diff --git a/tests/data/case_params/boundaries.yaml b/tests/v1/data/case_params/boundaries.yaml similarity index 100% rename from tests/data/case_params/boundaries.yaml rename to tests/v1/data/case_params/boundaries.yaml diff --git a/tests/data/case_params/freestream/yaml.yaml b/tests/v1/data/case_params/freestream/yaml.yaml similarity index 100% rename from tests/data/case_params/freestream/yaml.yaml rename to tests/v1/data/case_params/freestream/yaml.yaml diff --git a/tests/data/case_params/geometry.yaml b/tests/v1/data/case_params/geometry.yaml similarity index 100% rename from tests/data/case_params/geometry.yaml rename to tests/v1/data/case_params/geometry.yaml diff --git a/tests/data/case_params/incorrect.json b/tests/v1/data/case_params/incorrect.json similarity index 100% rename from tests/data/case_params/incorrect.json rename to tests/v1/data/case_params/incorrect.json diff --git a/tests/data/case_params/outputs.yaml b/tests/v1/data/case_params/outputs.yaml similarity index 100% rename from tests/data/case_params/outputs.yaml rename to tests/v1/data/case_params/outputs.yaml diff --git a/tests/data/case_params/xv15_bet_line_hover_good.json b/tests/v1/data/case_params/xv15_bet_line_hover_good.json similarity index 100% rename from tests/data/case_params/xv15_bet_line_hover_good.json rename to tests/v1/data/case_params/xv15_bet_line_hover_good.json diff --git a/tests/data/cases/case_1.json b/tests/v1/data/cases/case_1.json similarity index 100% rename from tests/data/cases/case_1.json rename to tests/v1/data/cases/case_1.json diff --git a/tests/data/cases/case_10.json b/tests/v1/data/cases/case_10.json similarity index 100% rename from tests/data/cases/case_10.json rename to tests/v1/data/cases/case_10.json diff --git a/tests/data/cases/case_11.json b/tests/v1/data/cases/case_11.json similarity index 100% rename from tests/data/cases/case_11.json rename to tests/v1/data/cases/case_11.json diff --git a/tests/data/cases/case_12.json b/tests/v1/data/cases/case_12.json similarity index 100% rename from tests/data/cases/case_12.json rename to tests/v1/data/cases/case_12.json diff --git a/tests/data/cases/case_13.json b/tests/v1/data/cases/case_13.json similarity index 100% rename from tests/data/cases/case_13.json rename to tests/v1/data/cases/case_13.json diff --git a/tests/data/cases/case_14_bet.json b/tests/v1/data/cases/case_14_bet.json similarity index 100% rename from tests/data/cases/case_14_bet.json rename to tests/v1/data/cases/case_14_bet.json diff --git a/tests/data/cases/case_15.json b/tests/v1/data/cases/case_15.json similarity index 100% rename from tests/data/cases/case_15.json rename to tests/v1/data/cases/case_15.json diff --git a/tests/data/cases/case_16.json b/tests/v1/data/cases/case_16.json similarity index 100% rename from tests/data/cases/case_16.json rename to tests/v1/data/cases/case_16.json diff --git a/tests/data/cases/case_18.json b/tests/v1/data/cases/case_18.json similarity index 100% rename from tests/data/cases/case_18.json rename to tests/v1/data/cases/case_18.json diff --git a/tests/data/cases/case_2.json b/tests/v1/data/cases/case_2.json similarity index 100% rename from tests/data/cases/case_2.json rename to tests/v1/data/cases/case_2.json diff --git a/tests/data/cases/case_20.json b/tests/v1/data/cases/case_20.json similarity index 100% rename from tests/data/cases/case_20.json rename to tests/v1/data/cases/case_20.json diff --git a/tests/data/cases/case_3.json b/tests/v1/data/cases/case_3.json similarity index 100% rename from tests/data/cases/case_3.json rename to tests/v1/data/cases/case_3.json diff --git a/tests/data/cases/case_4.json b/tests/v1/data/cases/case_4.json similarity index 100% rename from tests/data/cases/case_4.json rename to tests/v1/data/cases/case_4.json diff --git a/tests/data/cases/case_5.json b/tests/v1/data/cases/case_5.json similarity index 100% rename from tests/data/cases/case_5.json rename to tests/v1/data/cases/case_5.json diff --git a/tests/data/cases/case_6.json b/tests/v1/data/cases/case_6.json similarity index 100% rename from tests/data/cases/case_6.json rename to tests/v1/data/cases/case_6.json diff --git a/tests/data/cases/case_7.json b/tests/v1/data/cases/case_7.json similarity index 100% rename from tests/data/cases/case_7.json rename to tests/v1/data/cases/case_7.json diff --git a/tests/data/cases/case_8.json b/tests/v1/data/cases/case_8.json similarity index 100% rename from tests/data/cases/case_8.json rename to tests/v1/data/cases/case_8.json diff --git a/tests/data/cases/case_9.json b/tests/v1/data/cases/case_9.json similarity index 100% rename from tests/data/cases/case_9.json rename to tests/v1/data/cases/case_9.json diff --git a/tests/data/cases/case_HeatTransfer.json b/tests/v1/data/cases/case_HeatTransfer.json similarity index 100% rename from tests/data/cases/case_HeatTransfer.json rename to tests/v1/data/cases/case_HeatTransfer.json diff --git a/tests/data/cases/case_actuatorDisk.json b/tests/v1/data/cases/case_actuatorDisk.json similarity index 100% rename from tests/data/cases/case_actuatorDisk.json rename to tests/v1/data/cases/case_actuatorDisk.json diff --git a/tests/data/cases/case_bet.json b/tests/v1/data/cases/case_bet.json similarity index 100% rename from tests/data/cases/case_bet.json rename to tests/v1/data/cases/case_bet.json diff --git a/tests/data/cases/case_beta.json b/tests/v1/data/cases/case_beta.json similarity index 100% rename from tests/data/cases/case_beta.json rename to tests/v1/data/cases/case_beta.json diff --git a/tests/data/cases/case_boundaries.json b/tests/v1/data/cases/case_boundaries.json similarity index 100% rename from tests/data/cases/case_boundaries.json rename to tests/v1/data/cases/case_boundaries.json diff --git a/tests/data/cases/case_comments_sliding_interfaces.json b/tests/v1/data/cases/case_comments_sliding_interfaces.json similarity index 100% rename from tests/data/cases/case_comments_sliding_interfaces.json rename to tests/v1/data/cases/case_comments_sliding_interfaces.json diff --git a/tests/data/cases/case_customDynamics1.json b/tests/v1/data/cases/case_customDynamics1.json similarity index 100% rename from tests/data/cases/case_customDynamics1.json rename to tests/v1/data/cases/case_customDynamics1.json diff --git a/tests/data/cases/case_customDynamics2.json b/tests/v1/data/cases/case_customDynamics2.json similarity index 100% rename from tests/data/cases/case_customDynamics2.json rename to tests/v1/data/cases/case_customDynamics2.json diff --git a/tests/data/cases/case_cylinder_incompressible.json b/tests/v1/data/cases/case_cylinder_incompressible.json similarity index 100% rename from tests/data/cases/case_cylinder_incompressible.json rename to tests/v1/data/cases/case_cylinder_incompressible.json diff --git a/tests/data/cases/case_emptyDict.json b/tests/v1/data/cases/case_emptyDict.json similarity index 100% rename from tests/data/cases/case_emptyDict.json rename to tests/v1/data/cases/case_emptyDict.json diff --git a/tests/data/cases/case_emptyFile.json b/tests/v1/data/cases/case_emptyFile.json similarity index 100% rename from tests/data/cases/case_emptyFile.json rename to tests/v1/data/cases/case_emptyFile.json diff --git a/tests/data/cases/case_invalid.json b/tests/v1/data/cases/case_invalid.json similarity index 100% rename from tests/data/cases/case_invalid.json rename to tests/v1/data/cases/case_invalid.json diff --git a/tests/data/cases/case_isothermalWall.json b/tests/v1/data/cases/case_isothermalWall.json similarity index 100% rename from tests/data/cases/case_isothermalWall.json rename to tests/v1/data/cases/case_isothermalWall.json diff --git a/tests/data/cases/case_isothermalWall_miss.json b/tests/v1/data/cases/case_isothermalWall_miss.json similarity index 100% rename from tests/data/cases/case_isothermalWall_miss.json rename to tests/v1/data/cases/case_isothermalWall_miss.json diff --git a/tests/data/cases/case_isothermalWall_miss2.json b/tests/v1/data/cases/case_isothermalWall_miss2.json similarity index 100% rename from tests/data/cases/case_isothermalWall_miss2.json rename to tests/v1/data/cases/case_isothermalWall_miss2.json diff --git a/tests/data/cases/case_isothermalWall_noTemperature.json b/tests/v1/data/cases/case_isothermalWall_noTemperature.json similarity index 100% rename from tests/data/cases/case_isothermalWall_noTemperature.json rename to tests/v1/data/cases/case_isothermalWall_noTemperature.json diff --git a/tests/data/cases/case_plane.json b/tests/v1/data/cases/case_plane.json similarity index 100% rename from tests/data/cases/case_plane.json rename to tests/v1/data/cases/case_plane.json diff --git a/tests/data/cases/case_porousMedia.json b/tests/v1/data/cases/case_porousMedia.json similarity index 100% rename from tests/data/cases/case_porousMedia.json rename to tests/v1/data/cases/case_porousMedia.json diff --git a/tests/data/cases/case_rotor1.json b/tests/v1/data/cases/case_rotor1.json similarity index 100% rename from tests/data/cases/case_rotor1.json rename to tests/v1/data/cases/case_rotor1.json diff --git a/tests/data/cases/case_rotor2.json b/tests/v1/data/cases/case_rotor2.json similarity index 100% rename from tests/data/cases/case_rotor2.json rename to tests/v1/data/cases/case_rotor2.json diff --git a/tests/data/cases/case_two_rotor.json b/tests/v1/data/cases/case_two_rotor.json similarity index 100% rename from tests/data/cases/case_two_rotor.json rename to tests/v1/data/cases/case_two_rotor.json diff --git a/tests/data/cases/case_udd.json b/tests/v1/data/cases/case_udd.json similarity index 100% rename from tests/data/cases/case_udd.json rename to tests/v1/data/cases/case_udd.json diff --git a/tests/data/cases/case_udd_legacy.json b/tests/v1/data/cases/case_udd_legacy.json similarity index 100% rename from tests/data/cases/case_udd_legacy.json rename to tests/v1/data/cases/case_udd_legacy.json diff --git a/tests/data/cases/case_unsteady.json b/tests/v1/data/cases/case_unsteady.json similarity index 100% rename from tests/data/cases/case_unsteady.json rename to tests/v1/data/cases/case_unsteady.json diff --git a/tests/data/cases/case_wing1.json b/tests/v1/data/cases/case_wing1.json similarity index 100% rename from tests/data/cases/case_wing1.json rename to tests/v1/data/cases/case_wing1.json diff --git a/tests/data/cases/case_wing2.json b/tests/v1/data/cases/case_wing2.json similarity index 100% rename from tests/data/cases/case_wing2.json rename to tests/v1/data/cases/case_wing2.json diff --git a/tests/data/cases/params_units.json b/tests/v1/data/cases/params_units.json similarity index 100% rename from tests/data/cases/params_units.json rename to tests/v1/data/cases/params_units.json diff --git a/tests/data/cases/test_version_b16.json b/tests/v1/data/cases/test_version_b16.json similarity index 100% rename from tests/data/cases/test_version_b16.json rename to tests/v1/data/cases/test_version_b16.json diff --git a/tests/data/cases/web/2D_CRM.json b/tests/v1/data/cases/web/2D_CRM.json similarity index 100% rename from tests/data/cases/web/2D_CRM.json rename to tests/v1/data/cases/web/2D_CRM.json diff --git a/tests/data/cases/web/BackStep_Flow360.json b/tests/v1/data/cases/web/BackStep_Flow360.json similarity index 100% rename from tests/data/cases/web/BackStep_Flow360.json rename to tests/v1/data/cases/web/BackStep_Flow360.json diff --git a/tests/data/cases/web/CRM_Flow360.json b/tests/v1/data/cases/web/CRM_Flow360.json similarity index 100% rename from tests/data/cases/web/CRM_Flow360.json rename to tests/v1/data/cases/web/CRM_Flow360.json diff --git a/tests/data/cases/web/Flow360 (1).json b/tests/v1/data/cases/web/Flow360 (1).json similarity index 100% rename from tests/data/cases/web/Flow360 (1).json rename to tests/v1/data/cases/web/Flow360 (1).json diff --git a/tests/data/cases/web/Flow360 (2).json b/tests/v1/data/cases/web/Flow360 (2).json similarity index 100% rename from tests/data/cases/web/Flow360 (2).json rename to tests/v1/data/cases/web/Flow360 (2).json diff --git a/tests/data/cases/web/Flow360 (3).json b/tests/v1/data/cases/web/Flow360 (3).json similarity index 100% rename from tests/data/cases/web/Flow360 (3).json rename to tests/v1/data/cases/web/Flow360 (3).json diff --git a/tests/data/cases/web/Flow360 (4).json b/tests/v1/data/cases/web/Flow360 (4).json similarity index 100% rename from tests/data/cases/web/Flow360 (4).json rename to tests/v1/data/cases/web/Flow360 (4).json diff --git a/tests/data/cases/web/Flow360.json b/tests/v1/data/cases/web/Flow360.json similarity index 100% rename from tests/data/cases/web/Flow360.json rename to tests/v1/data/cases/web/Flow360.json diff --git a/tests/data/cases/web/Flow360_Stage1_1stOrd_6Deg.json b/tests/v1/data/cases/web/Flow360_Stage1_1stOrd_6Deg.json similarity index 100% rename from tests/data/cases/web/Flow360_Stage1_1stOrd_6Deg.json rename to tests/v1/data/cases/web/Flow360_Stage1_1stOrd_6Deg.json diff --git a/tests/data/cases/web/Flow360_Stage2_2ndOrd_6Deg.json b/tests/v1/data/cases/web/Flow360_Stage2_2ndOrd_6Deg.json similarity index 100% rename from tests/data/cases/web/Flow360_Stage2_2ndOrd_6Deg.json rename to tests/v1/data/cases/web/Flow360_Stage2_2ndOrd_6Deg.json diff --git a/tests/data/cases/web/Flow360_hover_pitch0.json b/tests/v1/data/cases/web/Flow360_hover_pitch0.json similarity index 100% rename from tests/data/cases/web/Flow360_hover_pitch0.json rename to tests/v1/data/cases/web/Flow360_hover_pitch0.json diff --git a/tests/data/cases/web/Flow360_hover_pitch3.json b/tests/v1/data/cases/web/Flow360_hover_pitch3.json similarity index 100% rename from tests/data/cases/web/Flow360_hover_pitch3.json rename to tests/v1/data/cases/web/Flow360_hover_pitch3.json diff --git a/tests/data/cases/web/Flow360_hover_pitch5.json b/tests/v1/data/cases/web/Flow360_hover_pitch5.json similarity index 100% rename from tests/data/cases/web/Flow360_hover_pitch5.json rename to tests/v1/data/cases/web/Flow360_hover_pitch5.json diff --git a/tests/data/cases/web/Flow360_v2.json b/tests/v1/data/cases/web/Flow360_v2.json similarity index 100% rename from tests/data/cases/web/Flow360_v2.json rename to tests/v1/data/cases/web/Flow360_v2.json diff --git a/tests/data/cases/web/NACA0012_FMLY2GL4_AOA15_SARC_2ndOrd_CFL100_Flow360.json b/tests/v1/data/cases/web/NACA0012_FMLY2GL4_AOA15_SARC_2ndOrd_CFL100_Flow360.json similarity index 100% rename from tests/data/cases/web/NACA0012_FMLY2GL4_AOA15_SARC_2ndOrd_CFL100_Flow360.json rename to tests/v1/data/cases/web/NACA0012_FMLY2GL4_AOA15_SARC_2ndOrd_CFL100_Flow360.json diff --git a/tests/data/cases/web/NACA4412_Flow360.json b/tests/v1/data/cases/web/NACA4412_Flow360.json similarity index 100% rename from tests/data/cases/web/NACA4412_Flow360.json rename to tests/v1/data/cases/web/NACA4412_Flow360.json diff --git a/tests/data/cases/web/adaptiveCFL.json b/tests/v1/data/cases/web/adaptiveCFL.json similarity index 100% rename from tests/data/cases/web/adaptiveCFL.json rename to tests/v1/data/cases/web/adaptiveCFL.json diff --git a/tests/data/cases/web/flow360_singleSlidingInterface-mixed-2.5flowthruPerRad-2deg-400steps.json b/tests/v1/data/cases/web/flow360_singleSlidingInterface-mixed-2.5flowthruPerRad-2deg-400steps.json similarity index 100% rename from tests/data/cases/web/flow360_singleSlidingInterface-mixed-2.5flowthruPerRad-2deg-400steps.json rename to tests/v1/data/cases/web/flow360_singleSlidingInterface-mixed-2.5flowthruPerRad-2deg-400steps.json diff --git a/tests/data/cases/web/flow360_singleSlidingInterface-steady.json b/tests/v1/data/cases/web/flow360_singleSlidingInterface-steady.json similarity index 100% rename from tests/data/cases/web/flow360_singleSlidingInterface-steady.json rename to tests/v1/data/cases/web/flow360_singleSlidingInterface-steady.json diff --git a/tests/data/cases/web/periodic_boundary_condition_tu_berlin_stator_flow360.json b/tests/v1/data/cases/web/periodic_boundary_condition_tu_berlin_stator_flow360.json similarity index 100% rename from tests/data/cases/web/periodic_boundary_condition_tu_berlin_stator_flow360.json rename to tests/v1/data/cases/web/periodic_boundary_condition_tu_berlin_stator_flow360.json diff --git a/tests/data/cases/web/s809Case.json b/tests/v1/data/cases/web/s809Case.json similarity index 100% rename from tests/data/cases/web/s809Case.json rename to tests/v1/data/cases/web/s809Case.json diff --git a/tests/data/cylinder.cgns b/tests/v1/data/cylinder.cgns similarity index 100% rename from tests/data/cylinder.cgns rename to tests/v1/data/cylinder.cgns diff --git a/tests/data/examples/release-22.1.2.0gt/keep b/tests/v1/data/examples/release-22.1.2.0gt/keep similarity index 100% rename from tests/data/examples/release-22.1.2.0gt/keep rename to tests/v1/data/examples/release-22.1.2.0gt/keep diff --git a/tests/data/examples/release-22.1.3.0ge/keep b/tests/v1/data/examples/release-22.1.3.0ge/keep similarity index 100% rename from tests/data/examples/release-22.1.3.0ge/keep rename to tests/v1/data/examples/release-22.1.3.0ge/keep diff --git a/tests/data/examples/release-22.1.3.2/keep b/tests/v1/data/examples/release-22.1.3.2/keep similarity index 100% rename from tests/data/examples/release-22.1.3.2/keep rename to tests/v1/data/examples/release-22.1.3.2/keep diff --git a/tests/data/examples/release-22.2.3.0le/keep b/tests/v1/data/examples/release-22.2.3.0le/keep similarity index 100% rename from tests/data/examples/release-22.2.3.0le/keep rename to tests/v1/data/examples/release-22.2.3.0le/keep diff --git a/tests/data/examples/release-22.3.3.0lt/keep b/tests/v1/data/examples/release-22.3.3.0lt/keep similarity index 100% rename from tests/data/examples/release-22.3.3.0lt/keep rename to tests/v1/data/examples/release-22.3.3.0lt/keep diff --git a/tests/data/examples/release-23.1.3.0/keep b/tests/v1/data/examples/release-23.1.3.0/keep similarity index 100% rename from tests/data/examples/release-23.1.3.0/keep rename to tests/v1/data/examples/release-23.1.3.0/keep diff --git a/tests/data/surface_mesh/airplaneGeometry.stl b/tests/v1/data/surface_mesh/airplaneGeometry.stl similarity index 100% rename from tests/data/surface_mesh/airplaneGeometry.stl rename to tests/v1/data/surface_mesh/airplaneGeometry.stl diff --git a/tests/data/surface_mesh/test.csm b/tests/v1/data/surface_mesh/test.csm similarity index 100% rename from tests/data/surface_mesh/test.csm rename to tests/v1/data/surface_mesh/test.csm diff --git a/tests/data/volume_mesh/cylinder.cgns b/tests/v1/data/volume_mesh/cylinder.cgns similarity index 100% rename from tests/data/volume_mesh/cylinder.cgns rename to tests/v1/data/volume_mesh/cylinder.cgns diff --git a/tests/data/volume_mesh/cylinder_case.json b/tests/v1/data/volume_mesh/cylinder_case.json similarity index 100% rename from tests/data/volume_mesh/cylinder_case.json rename to tests/v1/data/volume_mesh/cylinder_case.json diff --git a/tests/data/volume_mesh/cylinder_mesh.json b/tests/v1/data/volume_mesh/cylinder_mesh.json similarity index 100% rename from tests/data/volume_mesh/cylinder_mesh.json rename to tests/v1/data/volume_mesh/cylinder_mesh.json diff --git a/tests/data/volume_mesh/wing_tetra_mesh.json b/tests/v1/data/volume_mesh/wing_tetra_mesh.json similarity index 100% rename from tests/data/volume_mesh/wing_tetra_mesh.json rename to tests/v1/data/volume_mesh/wing_tetra_mesh.json diff --git a/tests/params/test_freestream.py b/tests/v1/params/test_freestream.py similarity index 97% rename from tests/params/test_freestream.py rename to tests/v1/params/test_freestream.py index bc9319ff0..c74f83035 100644 --- a/tests/params/test_freestream.py +++ b/tests/v1/params/test_freestream.py @@ -4,9 +4,9 @@ import pydantic.v1 as pd import pytest -import flow360 as fl -from flow360 import units as u -from flow360.component.flow360_params.flow360_params import ( +import flow360.v1 as fl +from flow360.component.v1 import units as u +from flow360.component.v1.flow360_params import ( FreestreamFromMach, FreestreamFromMachReynolds, FreestreamFromVelocity, diff --git a/tests/params/test_initial_condition.py b/tests/v1/params/test_initial_condition.py similarity index 90% rename from tests/params/test_initial_condition.py rename to tests/v1/params/test_initial_condition.py index 53c88b02b..745e5bc72 100644 --- a/tests/params/test_initial_condition.py +++ b/tests/v1/params/test_initial_condition.py @@ -2,10 +2,8 @@ import pytest -import flow360 as fl -from flow360.component.flow360_params.initial_condition import ( - ExpressionInitialCondition, -) +import flow360.v1 as fl +from flow360.component.v1.initial_condition import ExpressionInitialCondition from tests.utils import to_file_from_file_test assertions = unittest.TestCase("__init__") diff --git a/tests/params/test_outputs.py b/tests/v1/params/test_outputs.py similarity index 92% rename from tests/params/test_outputs.py rename to tests/v1/params/test_outputs.py index 56203f850..3bf0a0caa 100644 --- a/tests/params/test_outputs.py +++ b/tests/v1/params/test_outputs.py @@ -5,9 +5,9 @@ import pytest import unyt -import flow360 -import flow360.component.flow360_params.units as u -from flow360.component.flow360_params.flow360_output import ( +import flow360.component.v1.units as u +import flow360.v1 as v1 +from flow360.component.v1.flow360_output import ( IsoSurface, IsoSurfaceOutput, MonitorOutput, @@ -19,7 +19,7 @@ UserDefinedField, VolumeOutput, ) -from flow360.component.flow360_params.flow360_params import ( +from flow360.component.v1.flow360_params import ( AeroacousticOutput, Flow360Params, FreestreamFromMach, @@ -99,7 +99,7 @@ def test_surface_output(): output_fields=["Cp", "qcriterion"], ) - with flow360.SI_unit_system: + with v1.SI_unit_system: params = Flow360Params( surface_output=SurfaceOutput( output_fields=["Cp"], @@ -107,9 +107,9 @@ def test_surface_output(): output_format="both", ), boundaries={ - "1": flow360.NoSlipWall(name="wing"), - "2": flow360.SlipWall(name="symmetry"), - "3": flow360.FreestreamBoundary(name="freestream"), + "1": v1.NoSlipWall(name="wing"), + "2": v1.SlipWall(name="symmetry"), + "3": v1.FreestreamBoundary(name="freestream"), }, freestream=FreestreamFromMach(Mach=1, temperature=1, mu_ref=1), ) @@ -125,7 +125,7 @@ def test_surface_output(): else: assert surface_item["output_fields"] == ["Cp"] - with flow360.SI_unit_system: + with v1.SI_unit_system: params = Flow360Params( surface_output=SurfaceOutput( output_fields=["Cp", "solutionTurbulence", "nuHat"], @@ -133,9 +133,9 @@ def test_surface_output(): output_format="tecplot", ), boundaries={ - "1": flow360.NoSlipWall(name="wing"), - "2": flow360.SlipWall(name="symmetry"), - "3": flow360.FreestreamBoundary(name="freestream"), + "1": v1.NoSlipWall(name="wing"), + "2": v1.SlipWall(name="symmetry"), + "3": v1.FreestreamBoundary(name="freestream"), }, freestream=FreestreamFromMach(Mach=1, temperature=1, mu_ref=1), ) @@ -163,11 +163,11 @@ def test_slice_output(): output = SliceOutput( output_fields=["Cp", "qcriterion"], slices={ - "sliceName_1": flow360.Slice( + "sliceName_1": v1.Slice( slice_normal=(0, 1, 0), slice_origin=(0, 0.56413, 0) * u.m, ), - "sliceName_2": flow360.Slice( + "sliceName_2": v1.Slice( slice_normal=(0, 0, 1), slice_origin=(0, 0.56413 * u.inch, 0), output_fields=["Mach"], @@ -178,11 +178,11 @@ def test_slice_output(): output = SliceOutput( output_fields=["Cp", "qcriterion"], slices={ - "sliceName_1": flow360.Slice( + "sliceName_1": v1.Slice( slice_normal=(0, 1, 0), slice_origin=(0, 0.56413, 0) * u.m, ), - "sliceName_2": flow360.Slice( + "sliceName_2": v1.Slice( slice_normal=(0, 0, 1), slice_origin=(0, 0.56413, 0) * u.inch, output_fields=["Mach"], @@ -196,7 +196,7 @@ def test_slice_output(): output = SliceOutput( output_fields=["Cp", "qcriterion"], slices={ - "sliceName_1": flow360.Slice( + "sliceName_1": v1.Slice( slice_normal={0, 1}, slice_origin=(0, 0.56413, 0) * u.m, ) @@ -207,7 +207,7 @@ def test_slice_output(): output = SliceOutput( output_fields=["Cp", "qcriterion"], slices={ - "sliceName_1": flow360.Slice( + "sliceName_1": v1.Slice( slice_normal=(0, 1, 0), slice_origin={0, 0.56413} * u.m, ) @@ -217,11 +217,11 @@ def test_slice_output(): output = SliceOutput( output_fields=["Cp", "qcriterion"], slices={ - "sliceName_1": flow360.Slice( + "sliceName_1": v1.Slice( slice_normal=[0, 1, 0], slice_origin=(0, 0.56413, 0) * u.flow360_length_unit, ), - "sliceName_2": flow360.Slice( + "sliceName_2": v1.Slice( slice_normal=(0, 0, 1), slice_origin=(0, 0.56413, 0) * u.inch, output_fields=["Mach"], @@ -234,7 +234,7 @@ def test_slice_output(): to_file_from_file_test(output) output.output_format = "both" - with flow360.SI_unit_system: + with v1.SI_unit_system: params = Flow360Params( slice_output=output, boundaries={}, @@ -251,7 +251,7 @@ def test_slice_output(): else: assert {"Cp", "qcriterion"} == set(slice_item["output_fields"]) - with flow360.SI_unit_system: + with v1.SI_unit_system: params = Flow360Params( slice_output=SliceOutput( output_fields=[ @@ -261,11 +261,11 @@ def test_slice_output(): "solutionTurbulence", ], slices={ - "sliceName_1": flow360.Slice( + "sliceName_1": v1.Slice( slice_normal=[5, 1, 0], slice_origin=(0, 0.56413, 0) * u.flow360_length_unit, ), - "sliceName_2": flow360.Slice( + "sliceName_2": v1.Slice( slice_normal=(0, 1, 1), slice_origin=(0, 0.56413, 0) * u.inch, output_fields=["Mach"], @@ -337,7 +337,7 @@ def test_volume_output(): output.output_format = "both" - with flow360.SI_unit_system: + with v1.SI_unit_system: params = Flow360Params( volume_output=output, boundaries={}, @@ -347,7 +347,7 @@ def test_volume_output(): assert set(solver_params.volume_output.output_fields) == {"Cp", "qcriterion"} - with flow360.SI_unit_system: + with v1.SI_unit_system: """ Test addition of betMetrics/betMetricsPerDisk from slice output field """ @@ -356,11 +356,11 @@ def test_volume_output(): slice_output=SliceOutput( output_fields=["betMetrics"], slices={ - "sliceName_1": flow360.Slice( + "sliceName_1": v1.Slice( slice_normal=(0, 1, 0), slice_origin=(0, 0.56413, 0) * u.m, ), - "sliceName_2": flow360.Slice( + "sliceName_2": v1.Slice( slice_normal=(0, 1, 0), slice_origin=(50, 0.56413, 0) * u.m, output_fields=["betMetricsPerDisk"], @@ -383,7 +383,7 @@ def test_volume_output(): } output.output_fields = ["qcriterion", "Cp", "solutionTurbulence", "kOmega"] - with flow360.SI_unit_system: + with v1.SI_unit_system: """ Test removing duplicate output fields """ @@ -432,7 +432,7 @@ def test_iso_surface_output(): output.output_format = "both" - with flow360.SI_unit_system: + with v1.SI_unit_system: params = Flow360Params( iso_surface_output=output, boundaries={}, @@ -451,7 +451,7 @@ def test_iso_surface_output(): else: assert {"Mach"} == set(iso_surface_item["output_fields"]) - with flow360.SI_unit_system: + with v1.SI_unit_system: params = Flow360Params( iso_surface_output=IsoSurfaceOutput( output_fields=["Mach", "kOmega", "solutionTurbulence"], @@ -505,7 +505,7 @@ def test_monitor_output(): to_file_from_file_test(output) - with flow360.SI_unit_system: + with v1.SI_unit_system: params = Flow360Params( monitor_output=output, boundaries={}, @@ -523,7 +523,7 @@ def test_monitor_output(): else: assert {"Cp", "qcriterion", "Mach"} == set(monitor_item["output_fields"]) - with flow360.SI_unit_system: + with v1.SI_unit_system: params = Flow360Params( monitor_output=MonitorOutput( output_fields=["Cp", "solutionTurbulence", "kOmega"], @@ -548,7 +548,7 @@ def test_monitor_output(): def test_output_fields(): - with flow360.SI_unit_system: + with v1.SI_unit_system: params = Flow360Params( geometry=Geometry(mesh_unit=1), volume_output=VolumeOutput(output_fields=["Cp", "qcriterion", "my_var"]), @@ -556,7 +556,7 @@ def test_output_fields(): slice_output=SliceOutput( output_fields=["primitiveVars", "my_var", "mutRatio"], slices={ - "sliceName_1": flow360.Slice( + "sliceName_1": v1.Slice( slice_normal=[5, 1, 0], slice_origin=(0, 1.56413, 0), output_fields=["Mach"] ), }, @@ -598,7 +598,7 @@ def test_output_fields(): with pytest.raises( pd.ValidationError, match=r"surface_output:, prmitiveVars is not valid output field name." ): - with flow360.SI_unit_system: + with v1.SI_unit_system: Flow360Params( surface_output=SurfaceOutput(output_fields=["prmitiveVars", "my_var"]), boundaries={}, @@ -609,7 +609,7 @@ def test_output_fields(): with pytest.raises( pd.ValidationError, match=r"surface_output->wing:, my__var is not valid output field name." ): - with flow360.SI_unit_system: + with v1.SI_unit_system: Flow360Params( surface_output=SurfaceOutput( output_fields=["primitiveVars", "my__var"], diff --git a/tests/params/test_params_boundary.py b/tests/v1/params/test_params_boundary.py similarity index 98% rename from tests/params/test_params_boundary.py rename to tests/v1/params/test_params_boundary.py index 0b90f988b..8e08dd705 100644 --- a/tests/params/test_params_boundary.py +++ b/tests/v1/params/test_params_boundary.py @@ -3,8 +3,8 @@ import pydantic.v1 as pd import pytest -import flow360 as fl -from flow360.component.flow360_params.boundaries import ( +import flow360.v1 as fl +from flow360.component.v1.boundaries import ( FreestreamBoundary, HeatFluxWall, IsothermalWall, @@ -20,13 +20,13 @@ SubsonicOutflowPressure, WallFunction, ) -from flow360.component.flow360_params.flow360_params import ( +from flow360.component.v1.flow360_params import ( Flow360Params, FreestreamFromMach, MeshBoundary, SteadyTimeStepping, ) -from flow360.component.flow360_params.turbulence_quantities import TurbulenceQuantities +from flow360.component.v1.turbulence_quantities import TurbulenceQuantities from tests.utils import compare_to_ref, to_file_from_file_test assertions = unittest.TestCase("__init__") diff --git a/tests/params/test_porous_media.py b/tests/v1/params/test_porous_media.py similarity index 85% rename from tests/params/test_porous_media.py rename to tests/v1/params/test_porous_media.py index 5605f6cfa..27f5bcf95 100644 --- a/tests/params/test_porous_media.py +++ b/tests/v1/params/test_porous_media.py @@ -2,8 +2,8 @@ import pytest -from flow360 import SI_unit_system -from flow360.component.flow360_params.flow360_params import PorousMediumBox +from flow360.component.v1.flow360_params import PorousMediumBox +from flow360.v1 import SI_unit_system from tests.utils import to_file_from_file_test assertions = unittest.TestCase("__init__") diff --git a/tests/params/test_preconditioner.py b/tests/v1/params/test_preconditioner.py similarity index 84% rename from tests/params/test_preconditioner.py rename to tests/v1/params/test_preconditioner.py index a66eb4c62..618610540 100644 --- a/tests/params/test_preconditioner.py +++ b/tests/v1/params/test_preconditioner.py @@ -4,9 +4,9 @@ import pydantic.v1 as pd import pytest -import flow360 as fl -from flow360 import units as u -from flow360.component.flow360_params.flow360_params import FreestreamFromVelocity +import flow360.v1 as fl +from flow360.component.v1 import units as u +from flow360.component.v1.flow360_params import FreestreamFromVelocity assertions = unittest.TestCase("__init__") diff --git a/tests/params/test_reference_frame.py b/tests/v1/params/test_reference_frame.py similarity index 96% rename from tests/params/test_reference_frame.py rename to tests/v1/params/test_reference_frame.py index dd1c4a873..87c1c47b8 100644 --- a/tests/params/test_reference_frame.py +++ b/tests/v1/params/test_reference_frame.py @@ -3,8 +3,8 @@ import numpy as np import pytest -import flow360 as fl -from flow360 import units as u +import flow360.v1 as fl +from flow360.component.v1 import units as u assertions = unittest.TestCase("__init__") diff --git a/tests/params/test_rotational_models.py b/tests/v1/params/test_rotational_models.py similarity index 98% rename from tests/params/test_rotational_models.py rename to tests/v1/params/test_rotational_models.py index 42e42fa74..cbe856433 100644 --- a/tests/params/test_rotational_models.py +++ b/tests/v1/params/test_rotational_models.py @@ -3,8 +3,8 @@ import numpy as np import pytest -import flow360 as fl -from flow360.component.flow360_params.flow360_params import ( +import flow360.v1 as fl +from flow360.component.v1.flow360_params import ( ActuatorDisk, BETDisk, BETDiskChord, diff --git a/tests/params/test_sliding_interfaces.py b/tests/v1/params/test_sliding_interfaces.py similarity index 95% rename from tests/params/test_sliding_interfaces.py rename to tests/v1/params/test_sliding_interfaces.py index 816d42bde..b131a3bde 100644 --- a/tests/params/test_sliding_interfaces.py +++ b/tests/v1/params/test_sliding_interfaces.py @@ -2,10 +2,7 @@ import pytest -from flow360.component.flow360_params.flow360_params import ( - MeshSlidingInterface, - SlidingInterface, -) +from flow360.component.v1.flow360_params import MeshSlidingInterface, SlidingInterface from tests.utils import compare_to_ref, to_file_from_file_test assertions = unittest.TestCase("__init__") diff --git a/tests/params/test_solvers.py b/tests/v1/params/test_solvers.py similarity index 98% rename from tests/params/test_solvers.py rename to tests/v1/params/test_solvers.py index 6e3641693..296bd42ca 100644 --- a/tests/params/test_solvers.py +++ b/tests/v1/params/test_solvers.py @@ -3,13 +3,13 @@ import pydantic.v1 as pd import pytest -import flow360 as fl -from flow360.component.flow360_params.flow360_params import ( +import flow360.v1 as fl +from flow360.component.v1.flow360_params import ( Flow360Params, HeatEquationSolver, TransitionModelSolver, ) -from flow360.component.flow360_params.solvers import ( +from flow360.component.v1.solvers import ( HEAT_EQUATION_EVAL_FREQUENCY_STEADY, KOmegaSST, LinearSolver, diff --git a/tests/params/test_time_stepping.py b/tests/v1/params/test_time_stepping.py similarity index 95% rename from tests/params/test_time_stepping.py rename to tests/v1/params/test_time_stepping.py index 1457d2b46..baa1b6aa6 100644 --- a/tests/params/test_time_stepping.py +++ b/tests/v1/params/test_time_stepping.py @@ -4,15 +4,15 @@ import pydantic.v1 as pd import pytest -import flow360 as fl -from flow360 import units as u -from flow360.component.flow360_params.flow360_params import ( +import flow360.v1 as fl +from flow360.component.v1 import units as u +from flow360.component.v1.flow360_params import ( Flow360Params, FreestreamFromVelocity, Geometry, SteadyTimeStepping, ) -from flow360.component.flow360_params.time_stepping import UnsteadyTimeStepping +from flow360.component.v1.time_stepping import UnsteadyTimeStepping from tests.utils import to_file_from_file_test assertions = unittest.TestCase("__init__") diff --git a/tests/params/test_user_defined_dynamics.py b/tests/v1/params/test_user_defined_dynamics.py similarity index 95% rename from tests/params/test_user_defined_dynamics.py rename to tests/v1/params/test_user_defined_dynamics.py index 547685ec0..81a5b9818 100644 --- a/tests/params/test_user_defined_dynamics.py +++ b/tests/v1/params/test_user_defined_dynamics.py @@ -2,8 +2,8 @@ import pytest -import flow360 as fl -from flow360.component.flow360_params.flow360_params import UserDefinedDynamic +import flow360.v1 as fl +from flow360.component.v1.flow360_params import UserDefinedDynamic from tests.utils import to_file_from_file_test assertions = unittest.TestCase("__init__") diff --git a/tests/params/test_validator_aeroacoustics.py b/tests/v1/params/test_validator_aeroacoustics.py similarity index 76% rename from tests/params/test_validator_aeroacoustics.py rename to tests/v1/params/test_validator_aeroacoustics.py index df1ae082a..e01f570ff 100644 --- a/tests/params/test_validator_aeroacoustics.py +++ b/tests/v1/params/test_validator_aeroacoustics.py @@ -2,13 +2,10 @@ import pytest -import flow360 as fl -from flow360.component.flow360_params.boundaries import ( - NoSlipWall, - TranslationallyPeriodic, -) -from flow360.component.flow360_params.flow360_output import AeroacousticOutput -from flow360.component.flow360_params.flow360_params import Flow360Params +import flow360.v1 as fl +from flow360.component.v1.boundaries import NoSlipWall, TranslationallyPeriodic +from flow360.component.v1.flow360_output import AeroacousticOutput +from flow360.component.v1.flow360_params import Flow360Params assertions = unittest.TestCase("__init__") diff --git a/tests/params/test_validator_bet_disks.py b/tests/v1/params/test_validator_bet_disks.py similarity index 99% rename from tests/params/test_validator_bet_disks.py rename to tests/v1/params/test_validator_bet_disks.py index c86bc8209..6ddae217b 100644 --- a/tests/params/test_validator_bet_disks.py +++ b/tests/v1/params/test_validator_bet_disks.py @@ -3,8 +3,8 @@ import pytest -import flow360 as fl -from flow360.component.flow360_params.flow360_params import ( +import flow360.v1 as fl +from flow360.component.v1.flow360_params import ( BETDisk, BETDiskChord, BETDiskSectionalPolar, diff --git a/tests/params/test_validator_boundary.py b/tests/v1/params/test_validator_boundary.py similarity index 88% rename from tests/params/test_validator_boundary.py rename to tests/v1/params/test_validator_boundary.py index 954c79add..13c90cbfb 100644 --- a/tests/params/test_validator_boundary.py +++ b/tests/v1/params/test_validator_boundary.py @@ -2,9 +2,9 @@ import pytest -import flow360 as fl -from flow360.component.flow360_params.boundaries import NoSlipWall -from flow360.component.flow360_params.flow360_params import Flow360Params +import flow360.v1 as fl +from flow360.component.v1.boundaries import NoSlipWall +from flow360.component.v1.flow360_params import Flow360Params assertions = unittest.TestCase("__init__") diff --git a/tests/params/test_validator_cht_solver.py b/tests/v1/params/test_validator_cht_solver.py similarity index 94% rename from tests/params/test_validator_cht_solver.py rename to tests/v1/params/test_validator_cht_solver.py index b0dca6272..2b7bbc09e 100644 --- a/tests/params/test_validator_cht_solver.py +++ b/tests/v1/params/test_validator_cht_solver.py @@ -2,13 +2,10 @@ import pytest -import flow360 as fl -from flow360 import units as u -from flow360.component.flow360_params.boundaries import ( - SolidAdiabaticWall, - SolidIsothermalWall, -) -from flow360.component.flow360_params.flow360_output import ( +import flow360.v1 as fl +from flow360.component.v1 import units as u +from flow360.component.v1.boundaries import SolidAdiabaticWall, SolidIsothermalWall +from flow360.component.v1.flow360_output import ( IsoSurface, IsoSurfaceOutput, MonitorOutput, @@ -16,16 +13,14 @@ SurfaceOutput, VolumeOutput, ) -from flow360.component.flow360_params.flow360_params import Flow360Params -from flow360.component.flow360_params.initial_condition import ( - ExpressionInitialCondition, -) -from flow360.component.flow360_params.solvers import ( +from flow360.component.v1.flow360_params import Flow360Params +from flow360.component.v1.initial_condition import ExpressionInitialCondition +from flow360.component.v1.solvers import ( HeatEquationSolver, IncompressibleNavierStokesSolver, ) -from flow360.component.flow360_params.time_stepping import UnsteadyTimeStepping -from flow360.component.flow360_params.volume_zones import ( +from flow360.component.v1.time_stepping import UnsteadyTimeStepping +from flow360.component.v1.volume_zones import ( FluidDynamicsVolumeZone, HeatTransferVolumeZone, InitialConditionHeatTransfer, diff --git a/tests/params/test_validator_consistency_ddes_unsteady.py b/tests/v1/params/test_validator_consistency_ddes_unsteady.py similarity index 85% rename from tests/params/test_validator_consistency_ddes_unsteady.py rename to tests/v1/params/test_validator_consistency_ddes_unsteady.py index 44c814ab5..3e81e6ca2 100644 --- a/tests/params/test_validator_consistency_ddes_unsteady.py +++ b/tests/v1/params/test_validator_consistency_ddes_unsteady.py @@ -2,14 +2,11 @@ import pytest -import flow360 as fl -from flow360 import units as u -from flow360.component.flow360_params.flow360_params import ( - Flow360Params, - SteadyTimeStepping, -) -from flow360.component.flow360_params.solvers import SpalartAllmaras -from flow360.component.flow360_params.time_stepping import UnsteadyTimeStepping +import flow360.v1 as fl +from flow360.component.v1 import units as u +from flow360.component.v1.flow360_params import Flow360Params, SteadyTimeStepping +from flow360.component.v1.solvers import SpalartAllmaras +from flow360.component.v1.time_stepping import UnsteadyTimeStepping assertions = unittest.TestCase("__init__") diff --git a/tests/params/test_validator_equation_eval_frequency.py b/tests/v1/params/test_validator_equation_eval_frequency.py similarity index 87% rename from tests/params/test_validator_equation_eval_frequency.py rename to tests/v1/params/test_validator_equation_eval_frequency.py index 25ad3b712..ef4ea9576 100644 --- a/tests/params/test_validator_equation_eval_frequency.py +++ b/tests/v1/params/test_validator_equation_eval_frequency.py @@ -2,17 +2,11 @@ import pytest -import flow360 as fl -from flow360 import units as u -from flow360.component.flow360_params.flow360_params import ( - Flow360Params, - SteadyTimeStepping, -) -from flow360.component.flow360_params.solvers import ( - SpalartAllmaras, - TransitionModelSolver, -) -from flow360.component.flow360_params.time_stepping import UnsteadyTimeStepping +import flow360.v1 as fl +from flow360.component.v1 import units as u +from flow360.component.v1.flow360_params import Flow360Params, SteadyTimeStepping +from flow360.component.v1.solvers import SpalartAllmaras, TransitionModelSolver +from flow360.component.v1.time_stepping import UnsteadyTimeStepping assertions = unittest.TestCase("__init__") diff --git a/tests/params/test_validator_output_consistency.py b/tests/v1/params/test_validator_output_consistency.py similarity index 83% rename from tests/params/test_validator_output_consistency.py rename to tests/v1/params/test_validator_output_consistency.py index 8da85dcbd..aa42c5dd6 100644 --- a/tests/params/test_validator_output_consistency.py +++ b/tests/v1/params/test_validator_output_consistency.py @@ -2,14 +2,10 @@ import pytest -import flow360 as fl -from flow360.component.flow360_params.boundaries import ( - FreestreamBoundary, - NoSlipWall, - WallFunction, -) -from flow360.component.flow360_params.flow360_output import SurfaceOutput -from flow360.component.flow360_params.flow360_params import Flow360Params +import flow360.v1 as fl +from flow360.component.v1.boundaries import FreestreamBoundary, NoSlipWall, WallFunction +from flow360.component.v1.flow360_output import SurfaceOutput +from flow360.component.v1.flow360_params import Flow360Params assertions = unittest.TestCase("__init__") diff --git a/tests/params/test_validator_periodic_mapping.py b/tests/v1/params/test_validator_periodic_mapping.py similarity index 97% rename from tests/params/test_validator_periodic_mapping.py rename to tests/v1/params/test_validator_periodic_mapping.py index eb24f785d..8a6330d65 100644 --- a/tests/params/test_validator_periodic_mapping.py +++ b/tests/v1/params/test_validator_periodic_mapping.py @@ -2,13 +2,13 @@ import pytest -import flow360 as fl -from flow360.component.flow360_params.boundaries import ( +import flow360.v1 as fl +from flow360.component.v1.boundaries import ( NoSlipWall, RotationallyPeriodic, TranslationallyPeriodic, ) -from flow360.component.flow360_params.flow360_params import Flow360Params +from flow360.component.v1.flow360_params import Flow360Params assertions = unittest.TestCase("__init__") diff --git a/tests/params/test_volume_zones.py b/tests/v1/params/test_volume_zones.py similarity index 97% rename from tests/params/test_volume_zones.py rename to tests/v1/params/test_volume_zones.py index 1312619cf..d67101da6 100644 --- a/tests/params/test_volume_zones.py +++ b/tests/v1/params/test_volume_zones.py @@ -4,9 +4,9 @@ import pydantic.v1 as pd import pytest -import flow360 as fl -from flow360.component.flow360_params.flow360_params import VolumeZones -from flow360.component.flow360_params.volume_zones import ( +import flow360.v1 as fl +from flow360.component.v1.flow360_params import VolumeZones +from flow360.component.v1.volume_zones import ( FluidDynamicsVolumeZone, HeatTransferVolumeZone, InitialConditionHeatTransfer, diff --git a/tests/ref/case_params/actuator_disk/json.json b/tests/v1/ref/case_params/actuator_disk/json.json similarity index 100% rename from tests/ref/case_params/actuator_disk/json.json rename to tests/v1/ref/case_params/actuator_disk/json.json diff --git a/tests/ref/case_params/actuator_disk/yaml.yaml b/tests/v1/ref/case_params/actuator_disk/yaml.yaml similarity index 100% rename from tests/ref/case_params/actuator_disk/yaml.yaml rename to tests/v1/ref/case_params/actuator_disk/yaml.yaml diff --git a/tests/ref/case_params/boundaries/json.json b/tests/v1/ref/case_params/boundaries/json.json similarity index 100% rename from tests/ref/case_params/boundaries/json.json rename to tests/v1/ref/case_params/boundaries/json.json diff --git a/tests/ref/case_params/boundaries/yaml.yaml b/tests/v1/ref/case_params/boundaries/yaml.yaml similarity index 100% rename from tests/ref/case_params/boundaries/yaml.yaml rename to tests/v1/ref/case_params/boundaries/yaml.yaml diff --git a/tests/ref/case_params/heat_equation/ref.json b/tests/v1/ref/case_params/heat_equation/ref.json similarity index 100% rename from tests/ref/case_params/heat_equation/ref.json rename to tests/v1/ref/case_params/heat_equation/ref.json diff --git a/tests/ref/case_params/params.json b/tests/v1/ref/case_params/params.json similarity index 100% rename from tests/ref/case_params/params.json rename to tests/v1/ref/case_params/params.json diff --git a/tests/ref/case_params/params.yaml b/tests/v1/ref/case_params/params.yaml similarity index 100% rename from tests/ref/case_params/params.yaml rename to tests/v1/ref/case_params/params.yaml diff --git a/tests/ref/case_params/params_units.json b/tests/v1/ref/case_params/params_units.json similarity index 100% rename from tests/ref/case_params/params_units.json rename to tests/v1/ref/case_params/params_units.json diff --git a/tests/ref/case_params/params_units_converted.json b/tests/v1/ref/case_params/params_units_converted.json similarity index 100% rename from tests/ref/case_params/params_units_converted.json rename to tests/v1/ref/case_params/params_units_converted.json diff --git a/tests/ref/case_params/params_units_solver.json b/tests/v1/ref/case_params/params_units_solver.json similarity index 100% rename from tests/ref/case_params/params_units_solver.json rename to tests/v1/ref/case_params/params_units_solver.json diff --git a/tests/ref/case_params/sliding_interface/json.json b/tests/v1/ref/case_params/sliding_interface/json.json similarity index 100% rename from tests/ref/case_params/sliding_interface/json.json rename to tests/v1/ref/case_params/sliding_interface/json.json diff --git a/tests/ref/case_params/sliding_interface/yaml.yaml b/tests/v1/ref/case_params/sliding_interface/yaml.yaml similarity index 100% rename from tests/ref/case_params/sliding_interface/yaml.yaml rename to tests/v1/ref/case_params/sliding_interface/yaml.yaml diff --git a/tests/ref/flow360mesh/eg1.json b/tests/v1/ref/flow360mesh/eg1.json similarity index 100% rename from tests/ref/flow360mesh/eg1.json rename to tests/v1/ref/flow360mesh/eg1.json diff --git a/tests/ref/flow360mesh/eg2.json b/tests/v1/ref/flow360mesh/eg2.json similarity index 100% rename from tests/ref/flow360mesh/eg2.json rename to tests/v1/ref/flow360mesh/eg2.json diff --git a/tests/ref/flow360mesh/eg3.json b/tests/v1/ref/flow360mesh/eg3.json similarity index 100% rename from tests/ref/flow360mesh/eg3.json rename to tests/v1/ref/flow360mesh/eg3.json diff --git a/tests/ref/flow360mesh/mesh_boundary/json.json b/tests/v1/ref/flow360mesh/mesh_boundary/json.json similarity index 100% rename from tests/ref/flow360mesh/mesh_boundary/json.json rename to tests/v1/ref/flow360mesh/mesh_boundary/json.json diff --git a/tests/ref/flow360mesh/mesh_boundary/yaml.yaml b/tests/v1/ref/flow360mesh/mesh_boundary/yaml.yaml similarity index 100% rename from tests/ref/flow360mesh/mesh_boundary/yaml.yaml rename to tests/v1/ref/flow360mesh/mesh_boundary/yaml.yaml diff --git a/tests/ref/meshing_params/ref.json b/tests/v1/ref/meshing_params/ref.json similarity index 100% rename from tests/ref/meshing_params/ref.json rename to tests/v1/ref/meshing_params/ref.json diff --git a/tests/ref/meshing_params/ref.yaml b/tests/v1/ref/meshing_params/ref.yaml similarity index 100% rename from tests/ref/meshing_params/ref.yaml rename to tests/v1/ref/meshing_params/ref.yaml diff --git a/tests/test_base_model.py b/tests/v1/test_base_model.py similarity index 87% rename from tests/test_base_model.py rename to tests/v1/test_base_model.py index abe0e2d2c..bd8bbfaa9 100644 --- a/tests/test_base_model.py +++ b/tests/v1/test_base_model.py @@ -1,4 +1,4 @@ -from flow360.component.flow360_params.params_base import Flow360BaseModel +from flow360.component.v1.params_base import Flow360BaseModel def test_help(): diff --git a/tests/test_case.py b/tests/v1/test_case.py similarity index 99% rename from tests/test_case.py rename to tests/v1/test_case.py index 55b2c1a04..2627b6962 100644 --- a/tests/test_case.py +++ b/tests/v1/test_case.py @@ -1,6 +1,8 @@ import pytest -from flow360 import ( +from flow360.exceptions import Flow360RuntimeError, Flow360ValueError +from flow360.log import set_logging_level +from flow360.v1 import ( Case, Flow360Params, FreestreamFromVelocity, @@ -9,8 +11,6 @@ VolumeMesh, air, ) -from flow360.exceptions import Flow360RuntimeError, Flow360ValueError -from flow360.log import set_logging_level set_logging_level("DEBUG") diff --git a/tests/test_case_webapi.py b/tests/v1/test_case_webapi.py similarity index 96% rename from tests/test_case_webapi.py rename to tests/v1/test_case_webapi.py index f2a0f88ab..b19457b5f 100644 --- a/tests/test_case_webapi.py +++ b/tests/v1/test_case_webapi.py @@ -1,8 +1,8 @@ import pytest -from flow360 import Case from flow360.exceptions import Flow360RuntimeError from flow360.log import Logger, log +from flow360.v1 import Case Logger.log_to_file = False diff --git a/tests/test_dev_flow360_params.py b/tests/v1/test_dev_flow360_params.py similarity index 91% rename from tests/test_dev_flow360_params.py rename to tests/v1/test_dev_flow360_params.py index d3d396279..1b55c85de 100644 --- a/tests/test_dev_flow360_params.py +++ b/tests/v1/test_dev_flow360_params.py @@ -2,9 +2,9 @@ import pytest -import flow360 as fl +import flow360.v1 as fl -from .utils import compare_to_ref, to_file_from_file_test +from ..utils import compare_to_ref, to_file_from_file_test fl.UserConfig.disable_validation() # fl.Flow360Params = fl.component.flow360_params.flow360_params.UnvalidatedFlow360Params diff --git a/tests/test_examples.py b/tests/v1/test_examples.py similarity index 94% rename from tests/test_examples.py rename to tests/v1/test_examples.py index 338b0bcbf..6082e35fe 100644 --- a/tests/test_examples.py +++ b/tests/v1/test_examples.py @@ -2,8 +2,7 @@ import pytest -import flow360 -from flow360.examples import Airplane, Cylinder2D, OM6wing +from flow360.examples import Airplane, Cylinder2D, OM6wing, base_test_case from flow360.examples.base_test_case import BaseTestCase @@ -52,7 +51,7 @@ class TestCase(BaseTestCase): class url: case_json = "local://flow360.json" - flow360.examples.base_test_case.here = os.path.dirname(os.path.abspath(__file__)) + base_test_case.here = os.path.dirname(os.path.abspath(__file__)) TestCase.set_version("release-23.1.3.0") assert TestCase._get_version_prefix() == "release-23.1.3.0" diff --git a/tests/test_flow360_params.py b/tests/v1/test_flow360_params.py similarity index 98% rename from tests/test_flow360_params.py rename to tests/v1/test_flow360_params.py index 22cd5e1f0..9858730ce 100644 --- a/tests/test_flow360_params.py +++ b/tests/v1/test_flow360_params.py @@ -5,19 +5,19 @@ import pydantic.v1 as pd import pytest -import flow360 as fl -from flow360 import units as u -from flow360.component.flow360_params.flow360_params import ( +import flow360.v1 as fl +from flow360.component.v1 import units as u +from flow360.component.v1.flow360_params import ( Flow360MeshParams, Flow360Params, FreestreamFromVelocity, MeshBoundary, PorousMediumBox, ) -from flow360.component.flow360_params.time_stepping import UnsteadyTimeStepping +from flow360.component.v1.time_stepping import UnsteadyTimeStepping from flow360.exceptions import Flow360RuntimeError -from .utils import compare_to_ref, to_file_from_file_test +from ..utils import compare_to_ref, to_file_from_file_test assertions = unittest.TestCase("__init__") diff --git a/tests/test_folders.py b/tests/v1/test_folders.py similarity index 94% rename from tests/test_folders.py rename to tests/v1/test_folders.py index 33b753562..7a60536ce 100644 --- a/tests/test_folders.py +++ b/tests/v1/test_folders.py @@ -1,5 +1,5 @@ -from flow360 import Case, Folder from flow360.log import set_logging_level +from flow360.v1 import Case, Folder set_logging_level("DEBUG") diff --git a/tests/test_handle_version_and_unit_system.py b/tests/v1/test_handle_version_and_unit_system.py similarity index 80% rename from tests/test_handle_version_and_unit_system.py rename to tests/v1/test_handle_version_and_unit_system.py index f81065e22..2144e2633 100644 --- a/tests/test_handle_version_and_unit_system.py +++ b/tests/v1/test_handle_version_and_unit_system.py @@ -4,10 +4,11 @@ import pydantic.v1 as pd import pytest -import flow360 -import flow360.component.flow360_params.units as u -from flow360 import Flow360Params +import flow360.component.v1.units as u +import flow360.v1 as v1 from flow360.exceptions import Flow360NotImplementedError, Flow360RuntimeError +from flow360.v1 import Flow360Params +from flow360.version import __version__ params_old_version = { "version": "0.2.0b01", @@ -106,7 +107,7 @@ def test_import_no_unit_system_with_context(): json.dump(params_no_unit_system, temp_file) with pytest.raises(Flow360RuntimeError): - with flow360.flow360_unit_system: + with v1.flow360_unit_system: Flow360Params(temp_file.name) @@ -116,7 +117,7 @@ def test_import_with_unit_system_no_context(): params = Flow360Params(temp_file.name) assert params - assert params.unit_system == flow360.SI_unit_system + assert params.unit_system == v1.SI_unit_system def test_import_with_unit_system_with_context(): @@ -124,7 +125,7 @@ def test_import_with_unit_system_with_context(): json.dump(params_current_version, temp_file) with pytest.raises(Flow360RuntimeError): - with flow360.SI_unit_system: + with v1.SI_unit_system: Flow360Params(temp_file.name) @@ -150,30 +151,30 @@ def test_copy_with_unit_system_with_context(): assert params # passes, the models are consistent - with flow360.SI_unit_system: + with v1.SI_unit_system: params_copy = params.copy() assert params_copy # fails, the models are inconsistent - with flow360.CGS_unit_system: + with v1.CGS_unit_system: with pytest.raises(Flow360RuntimeError): params_copy = params.copy() def test_create_no_unit_system_no_context(): with pytest.raises(Flow360RuntimeError): - flow360.Flow360Params( - geometry=flow360.Geometry( + v1.Flow360Params( + geometry=v1.Geometry( ref_area=1 * u.m**2, moment_length=(1.47602, 0.801672958512342, 1.47602) * u.inch, moment_center=(1, 2, 3) * u.flow360_length_unit, mesh_unit=u.mm, ), - fluid_properties=flow360.air, - freestream=flow360.FreestreamFromVelocity(velocity=286 * u.m / u.s), - time_stepping=flow360.UnsteadyTimeStepping( + fluid_properties=v1.air, + freestream=v1.FreestreamFromVelocity(velocity=286 * u.m / u.s), + time_stepping=v1.UnsteadyTimeStepping( max_pseudo_steps=500, - CFL=flow360.AdaptiveCFL(), + CFL=v1.AdaptiveCFL(), time_step_size=1.2 * u.s, physical_steps=10, ), @@ -182,40 +183,40 @@ def test_create_no_unit_system_no_context(): def test_create_with_unit_system_no_context(): with pytest.raises(Flow360RuntimeError): - flow360.Flow360Params( - geometry=flow360.Geometry( + v1.Flow360Params( + geometry=v1.Geometry( ref_area=1 * u.m**2, moment_length=(1.47602, 0.801672958512342, 1.47602) * u.inch, moment_center=(1, 2, 3) * u.flow360_length_unit, mesh_unit=u.mm, ), - fluid_properties=flow360.air, - freestream=flow360.FreestreamFromVelocity(velocity=286 * u.m / u.s), - time_stepping=flow360.UnsteadyTimeStepping( + fluid_properties=v1.air, + freestream=v1.FreestreamFromVelocity(velocity=286 * u.m / u.s), + time_stepping=v1.UnsteadyTimeStepping( max_pseudo_steps=500, - CFL=flow360.AdaptiveCFL(), + CFL=v1.AdaptiveCFL(), time_step_size=1.2 * u.s, physical_steps=10, ), - unit_system=flow360.SI_unit_system, + unit_system=v1.SI_unit_system, ) def test_create_no_unit_system_with_context(): - with flow360.SI_unit_system: - flow360.Flow360Params( - geometry=flow360.Geometry( + with v1.SI_unit_system: + v1.Flow360Params( + geometry=v1.Geometry( ref_area=1, moment_length=(1.47602, 0.801672958512342, 1.47602) * u.inch, moment_center=(1, 2, 3) * u.flow360_length_unit, mesh_unit=u.mm, ), boundaries={}, - fluid_properties=flow360.air, - freestream=flow360.FreestreamFromVelocity(velocity=286), - time_stepping=flow360.UnsteadyTimeStepping( + fluid_properties=v1.air, + freestream=v1.FreestreamFromVelocity(velocity=286), + time_stepping=v1.UnsteadyTimeStepping( max_pseudo_steps=500, - CFL=flow360.AdaptiveCFL(), + CFL=v1.AdaptiveCFL(), time_step_size=1.2 * u.s, physical_steps=10, ), @@ -223,50 +224,50 @@ def test_create_no_unit_system_with_context(): def test_create_with_unit_system_with_context(): - with flow360.SI_unit_system: - flow360.Flow360Params( - geometry=flow360.Geometry( + with v1.SI_unit_system: + v1.Flow360Params( + geometry=v1.Geometry( ref_area=1, moment_length=(1.47602, 0.801672958512342, 1.47602) * u.inch, moment_center=(1, 2, 3) * u.flow360_length_unit, mesh_unit=u.mm, ), boundaries={}, - fluid_properties=flow360.air, - freestream=flow360.FreestreamFromVelocity(velocity=286), - time_stepping=flow360.UnsteadyTimeStepping( + fluid_properties=v1.air, + freestream=v1.FreestreamFromVelocity(velocity=286), + time_stepping=v1.UnsteadyTimeStepping( max_pseudo_steps=500, - CFL=flow360.AdaptiveCFL(), + CFL=v1.AdaptiveCFL(), time_step_size=1.2 * u.s, physical_steps=10, ), - unit_system=flow360.SI_unit_system, + unit_system=v1.SI_unit_system, ) with pytest.raises(Flow360RuntimeError): - with flow360.CGS_unit_system: - flow360.Flow360Params( - geometry=flow360.Geometry( + with v1.CGS_unit_system: + v1.Flow360Params( + geometry=v1.Geometry( ref_area=1, moment_length=(1.47602, 0.801672958512342, 1.47602) * u.inch, moment_center=(1, 2, 3) * u.flow360_length_unit, mesh_unit=u.mm, ), boundaries={}, - fluid_properties=flow360.air, - freestream=flow360.FreestreamFromVelocity(velocity=286), - time_stepping=flow360.UnsteadyTimeStepping( + fluid_properties=v1.air, + freestream=v1.FreestreamFromVelocity(velocity=286), + time_stepping=v1.UnsteadyTimeStepping( max_pseudo_steps=500, - CFL=flow360.AdaptiveCFL(), + CFL=v1.AdaptiveCFL(), time_step_size=1.2 * u.s, physical_steps=10, ), - unit_system=flow360.SI_unit_system, + unit_system=v1.SI_unit_system, ) def test_change_version(): - with flow360.SI_unit_system: + with v1.SI_unit_system: params = Flow360Params(**params_no_hash) with pytest.raises(ValueError): params.version = "changed" @@ -277,7 +278,7 @@ def test_parse_with_version(): json.dump(params_no_hash, temp_file) params = Flow360Params(temp_file.name) - assert params.version == flow360.__version__ + assert params.version == __version__ def test_parse_no_version(): @@ -298,12 +299,12 @@ def test_parse_wrong_version(): def test_parse_with_hash(): with pytest.raises(pd.ValidationError): - with flow360.SI_unit_system: + with v1.SI_unit_system: Flow360Params(**params_current_version) def test_parse_no_hash(): - with flow360.SI_unit_system: + with v1.SI_unit_system: params = Flow360Params(**params_no_hash) assert params_no_hash.get("hash") is None assert not hasattr(params, "hash") @@ -311,5 +312,5 @@ def test_parse_no_hash(): def test_parse_wrong_hash(): with pytest.raises(pd.ValidationError): - with flow360.SI_unit_system: + with v1.SI_unit_system: Flow360Params(**params_wrong_hash) diff --git a/tests/test_meshing_params.py b/tests/v1/test_meshing_params.py similarity index 98% rename from tests/test_meshing_params.py rename to tests/v1/test_meshing_params.py index a71bcbf18..a72566987 100644 --- a/tests/test_meshing_params.py +++ b/tests/v1/test_meshing_params.py @@ -1,6 +1,6 @@ import pytest -from flow360.component.meshing.params import ( +from flow360.component.v1.meshing.params import ( Aniso, BoxRefinement, CylinderRefinement, @@ -16,7 +16,7 @@ VolumeMeshingParams, ) -from .utils import compare_to_ref, to_file_from_file_test +from ..utils import compare_to_ref, to_file_from_file_test @pytest.fixture(autouse=True) diff --git a/tests/test_remote_resource_logs.py b/tests/v1/test_remote_resource_logs.py similarity index 100% rename from tests/test_remote_resource_logs.py rename to tests/v1/test_remote_resource_logs.py diff --git a/tests/test_resource_base_model.py b/tests/v1/test_resource_base_model.py similarity index 100% rename from tests/test_resource_base_model.py rename to tests/v1/test_resource_base_model.py diff --git a/tests/test_schema_generator.py b/tests/v1/test_schema_generator.py similarity index 98% rename from tests/test_schema_generator.py rename to tests/v1/test_schema_generator.py index 05711283d..37bddc50a 100644 --- a/tests/test_schema_generator.py +++ b/tests/v1/test_schema_generator.py @@ -1,6 +1,6 @@ import json -import flow360 as fl +import flow360.v1 as fl def test_schema_generators(): diff --git a/tests/test_services_v1.py b/tests/v1/test_services_v1.py similarity index 99% rename from tests/test_services_v1.py rename to tests/v1/test_services_v1.py index 5999d3820..1da71c11f 100644 --- a/tests/test_services_v1.py +++ b/tests/v1/test_services_v1.py @@ -3,8 +3,8 @@ import pytest -import flow360 as fl -from flow360.component.flow360_params import services +import flow360.v1 as fl +from flow360.component.v1 import services @pytest.fixture(autouse=True) diff --git a/tests/test_surface_mesh.py b/tests/v1/test_surface_mesh.py similarity index 83% rename from tests/test_surface_mesh.py rename to tests/v1/test_surface_mesh.py index b95858036..fe5722c6d 100644 --- a/tests/test_surface_mesh.py +++ b/tests/v1/test_surface_mesh.py @@ -3,9 +3,7 @@ import pytest from flow360 import exceptions as ex -from flow360.component.meshing.params import Face, SurfaceMeshingParams from flow360.component.surface_mesh import SurfaceMesh -from flow360.component.utils import MeshFileFormat assertions = unittest.TestCase("__init__") diff --git a/tests/test_types_v1.py b/tests/v1/test_types_v1.py similarity index 100% rename from tests/test_types_v1.py rename to tests/v1/test_types_v1.py diff --git a/tests/test_unit_system_v1.py b/tests/v1/test_unit_system_v1.py similarity index 98% rename from tests/test_unit_system_v1.py rename to tests/v1/test_unit_system_v1.py index bd6f7a7cf..7a4a00ebe 100644 --- a/tests/test_unit_system_v1.py +++ b/tests/v1/test_unit_system_v1.py @@ -4,10 +4,10 @@ import pydantic.v1 as pd import pytest -import flow360 as fl -from flow360 import units as u -from flow360.component.flow360_params.params_base import Flow360BaseModel -from flow360.component.flow360_params.unit_system import ( +import flow360.v1 as fl +from flow360.component.v1 import units as u +from flow360.component.v1.params_base import Flow360BaseModel +from flow360.component.v1.unit_system import ( AngularVelocityType, AreaType, DensityType, diff --git a/tests/test_updater.py b/tests/v1/test_updater.py similarity index 96% rename from tests/test_updater.py rename to tests/v1/test_updater.py index 0bfd43642..27d5e8946 100644 --- a/tests/test_updater.py +++ b/tests/v1/test_updater.py @@ -3,17 +3,12 @@ import pytest -import flow360 as fl -from flow360.component.flow360_params.flow360_legacy import LinearSolverLegacy -from flow360.component.flow360_params.initial_condition import ( - ExpressionInitialCondition, -) -from flow360.component.flow360_params.updater import ( - UPDATE_MAP, - _find_update_path, - _no_update, -) +import flow360.v1 as fl +from flow360.component.v1.flow360_legacy import LinearSolverLegacy +from flow360.component.v1.initial_condition import ExpressionInitialCondition +from flow360.component.v1.updater import UPDATE_MAP, _find_update_path, _no_update from flow360.exceptions import Flow360NotImplementedError +from flow360.version import __version__ @pytest.fixture(autouse=True) @@ -271,4 +266,4 @@ def test_updater_map(): assert len(update_path) == 3 update_path = _find_update_path(version_from=UPDATE_MAP[0][0], version_to=UPDATE_MAP[-1][1]) - update_path = _find_update_path(version_from=UPDATE_MAP[0][0], version_to=fl.__version__) + update_path = _find_update_path(version_from=UPDATE_MAP[0][0], version_to=__version__) diff --git a/tests/test_validator_valid_output_fields.py b/tests/v1/test_validator_valid_output_fields.py similarity index 90% rename from tests/test_validator_valid_output_fields.py rename to tests/v1/test_validator_valid_output_fields.py index bebac9914..7f97c398f 100644 --- a/tests/test_validator_valid_output_fields.py +++ b/tests/v1/test_validator_valid_output_fields.py @@ -2,10 +2,10 @@ import pytest -import flow360 as fl -import flow360.component.flow360_params.units as u -from flow360.component.flow360_params.boundaries import FreestreamBoundary, NoSlipWall -from flow360.component.flow360_params.flow360_output import ( +import flow360.component.v1.units as u +import flow360.v1 as fl +from flow360.component.v1.boundaries import FreestreamBoundary, NoSlipWall +from flow360.component.v1.flow360_output import ( IsoSurface, IsoSurfaceOutput, MonitorOutput, @@ -17,8 +17,8 @@ SurfaceOutput, VolumeOutput, ) -from flow360.component.flow360_params.flow360_params import Flow360Params -from flow360.component.flow360_params.solvers import NavierStokesSolver +from flow360.component.v1.flow360_params import Flow360Params +from flow360.component.v1.solvers import NavierStokesSolver assertions = unittest.TestCase("__init__") diff --git a/tests/test_volume_mesh.py b/tests/v1/test_volume_mesh.py similarity index 95% rename from tests/test_volume_mesh.py rename to tests/v1/test_volume_mesh.py index 2ccb9e4b9..a937ecee5 100644 --- a/tests/test_volume_mesh.py +++ b/tests/v1/test_volume_mesh.py @@ -1,14 +1,14 @@ import pytest -import flow360 -from flow360.component.flow360_params.boundaries import NoSlipWall -from flow360.component.flow360_params.flow360_params import ( +import flow360.v1 as v1 +from flow360.component.utils import CompressionFormat, MeshFileFormat, UGRIDEndianness +from flow360.component.v1.boundaries import NoSlipWall +from flow360.component.v1.flow360_params import ( Flow360MeshParams, Flow360Params, FreestreamFromMach, MeshBoundary, ) -from flow360.component.utils import CompressionFormat, MeshFileFormat, UGRIDEndianness from flow360.component.volume_mesh import ( VolumeMesh, VolumeMeshMeta, @@ -19,7 +19,7 @@ from flow360.exceptions import Flow360FileError, Flow360RuntimeError, Flow360ValueError from tests.data.volume_mesh_list import volume_mesh_list_raw -from .utils import compare_to_ref, to_file_from_file_test +from ..utils import compare_to_ref, to_file_from_file_test @pytest.fixture(autouse=True) @@ -47,7 +47,7 @@ def test_get_no_slip_walls(): assert walls assert len(walls) == 3 - with flow360.SI_unit_system: + with v1.SI_unit_system: param = Flow360Params( boundaries={ "fluid/fuselage": NoSlipWall(), @@ -66,7 +66,7 @@ def test_get_no_slip_walls(): def test_validate_cgns(): - with flow360.SI_unit_system: + with v1.SI_unit_system: param = Flow360Params( boundaries={ "fluid/fuselage": NoSlipWall(), diff --git a/tests/test_volume_mesh_webapi.py b/tests/v1/test_volume_mesh_webapi.py similarity index 100% rename from tests/test_volume_mesh_webapi.py rename to tests/v1/test_volume_mesh_webapi.py diff --git a/tools/integrations/schema_generation.py b/tools/integrations/schema_generation.py index ef5b3acd4..0bb9c922f 100644 --- a/tools/integrations/schema_generation.py +++ b/tools/integrations/schema_generation.py @@ -4,26 +4,19 @@ import pydantic.v1 as pd -import flow360 as fl -from flow360.component.flow360_params.flow360_params import ( +import flow360.v1 as fl +from flow360.component.v1.flow360_params import ( BETDiskChord, BETDiskSectionalPolar, BETDiskTwist, ) -from flow360.component.flow360_params.initial_condition import ( +from flow360.component.v1.initial_condition import ( ExpressionInitialCondition, ModifiedRestartSolution, ) -from flow360.component.flow360_params.params_base import ( - Flow360BaseModel, - Flow360SortableBaseModel, -) -from flow360.component.flow360_params.unit_system import ( - DensityType, - PressureType, - TemperatureType, -) -from flow360.component.flow360_params.volume_zones import ( +from flow360.component.v1.params_base import Flow360BaseModel, Flow360SortableBaseModel +from flow360.component.v1.unit_system import DensityType, PressureType, TemperatureType +from flow360.component.v1.volume_zones import ( ReferenceFrame, ReferenceFrameDynamic, ReferenceFrameExpression, diff --git a/tools/integrations/tests/_test_webui_workbench_integration.py b/tools/integrations/tests/_test_webui_workbench_integration.py index 256edef93..d8d383b2a 100644 --- a/tools/integrations/tests/_test_webui_workbench_integration.py +++ b/tools/integrations/tests/_test_webui_workbench_integration.py @@ -1,7 +1,7 @@ import json import os -import flow360 as fl +import flow360.v1 as fl from flow360.component.simulation.meshing_param.face_params import ( BoundaryLayer, SurfaceRefinement, diff --git a/tools/integrations/unit_defaults.py b/tools/integrations/unit_defaults.py index 18e5640ef..8ce5a8de6 100644 --- a/tools/integrations/unit_defaults.py +++ b/tools/integrations/unit_defaults.py @@ -3,8 +3,8 @@ import pydantic.v1 as pd -import flow360 as fl -from flow360.component.flow360_params.params_base import Flow360BaseModel +import flow360.v1 as fl +from flow360.component.v1.params_base import Flow360BaseModel class UnitDefaults(Flow360BaseModel):