diff --git a/flow360/cloud/flow360_requests.py b/flow360/cloud/flow360_requests.py index 88e6e6b25..a3930b97d 100644 --- a/flow360/cloud/flow360_requests.py +++ b/flow360/cloud/flow360_requests.py @@ -1,15 +1,26 @@ """Requests module""" -from typing import List, Optional, Union +from datetime import datetime +from typing import Annotated, List, Optional, Union import pydantic as pd_v2 import pydantic.v1 as pd from pydantic.alias_generators import to_camel from typing_extensions import Literal +from ..component.utils import is_valid_uuid + LengthUnitType = Literal["m", "mm", "cm", "inch", "ft"] +def _valid_id_validator(input_id: str): + is_valid_uuid(input_id) + return input_id + + +IDStringType = Annotated[str, pd_v2.AfterValidator(_valid_id_validator)] + + ###==== V1 API Payload definition ===### @@ -153,3 +164,67 @@ class NewReportRequest(Flow360RequestsV2): resources: List[_Resource] config_json: str solver_version: str + + +class DraftCreateRequest(Flow360RequestsV2): + """Data model for draft create request""" + + name: Optional[str] = pd.Field(None) + project_id: IDStringType = pd.Field() + source_item_id: IDStringType = pd.Field() + source_item_type: Literal[ + "Project", "Folder", "Geometry", "SurfaceMesh", "VolumeMesh", "Case", "Draft" + ] = pd.Field() + solver_version: str = pd.Field() + fork_case: bool = pd.Field() + + @pd_v2.field_validator("name", mode="after") + @classmethod + def _generate_default_name(cls, values): + if values is None: + values = "Draft " + datetime.now().strftime("%m-%d %H:%M:%S") + return values + + +class ForceCreationConfig(Flow360RequestsV2): + """Data model for force creation configuration""" + + start_from: Literal["SurfaceMesh", "VolumeMesh", "Case"] = pd.Field() + + +class DraftRunRequest(Flow360RequestsV2): + """Data model for draft run request""" + + up_to: Literal["SurfaceMesh", "VolumeMesh", "Case"] = pd.Field() + use_in_house: bool = pd.Field() + force_creation_config: Optional[ForceCreationConfig] = pd.Field( + None, + ) + source_item_type: Literal["Geometry", "SurfaceMesh", "VolumeMesh", "Case"] = pd.Field( + exclude=True + ) + + @pd_v2.model_validator(mode="after") + def _validate_force_creation_config(self): + # pylint: disable=no-member + + order = {"Geometry": 0, "SurfaceMesh": 1, "VolumeMesh": 2, "Case": 3} + source_order = order[self.source_item_type] + up_to_order = order[self.up_to] + + if self.force_creation_config is not None: + force_start_order = order[self.force_creation_config.start_from] + if (force_start_order <= source_order and self.source_item_type != "Case") or ( + self.source_item_type == "Case" and self.force_creation_config.start_from != "Case" + ): + raise ValueError( + f"Invalid force creation configuration: 'start_from' ({self.force_creation_config.start_from}) " + f"must be later than 'source_item_type' ({self.source_item_type})." + ) + + if force_start_order > up_to_order: + raise ValueError( + f"Invalid force creation configuration: 'start_from' ({self.force_creation_config.start_from}) " + f"cannot be later than 'up_to' ({self.up_to})." + ) + return self diff --git a/flow360/component/project.py b/flow360/component/project.py index 46bf3fe86..426a4e92d 100644 --- a/flow360/component/project.py +++ b/flow360/component/project.py @@ -937,6 +937,7 @@ def _run( run_async: bool, solver_version: str, use_beta_mesher: bool, + **kwargs, ): """ Runs a simulation for the project. @@ -982,11 +983,14 @@ def _run( "\n>> Validation error found in the simulation params! Errors are: " + error_msg ) + source_item_type = self.metadata.root_item_type.value if fork_from is None else "Case" + start_from = kwargs.get("start_from", None) + draft = Draft.create( name=draft_name, project_id=self.metadata.id, source_item_id=self.metadata.root_item_id if fork_from is None else fork_from.id, - source_item_type=(self.metadata.root_item_type.value if fork_from is None else "Case"), + source_item_type=source_item_type, solver_version=solver_version if solver_version else self.solver_version, fork_case=fork_from is not None, ).submit() @@ -994,7 +998,12 @@ def _run( draft.update_simulation_params(params) try: - destination_id = draft.run_up_to_target_asset(target, use_beta_mesher=use_beta_mesher) + destination_id = draft.run_up_to_target_asset( + target, + source_item_type=source_item_type, + use_beta_mesher=use_beta_mesher, + start_from=start_from, + ) except RuntimeError: return None @@ -1036,6 +1045,7 @@ def generate_surface_mesh( run_async: bool = True, solver_version: str = None, use_beta_mesher: bool = False, + **kwargs, ): """ Runs the surface mesher for the project. @@ -1069,6 +1079,7 @@ def generate_surface_mesh( fork_from=None, solver_version=solver_version, use_beta_mesher=use_beta_mesher, + **kwargs, ) return surface_mesh @@ -1080,6 +1091,7 @@ def generate_volume_mesh( run_async: bool = True, solver_version: str = None, use_beta_mesher: bool = False, + **kwargs, ): """ Runs the volume mesher for the project. @@ -1116,6 +1128,7 @@ def generate_volume_mesh( fork_from=None, solver_version=solver_version, use_beta_mesher=use_beta_mesher, + **kwargs, ) return volume_mesh @@ -1128,6 +1141,7 @@ def run_case( fork_from: Case = None, solver_version: str = None, use_beta_mesher: bool = False, + **kwargs, ): """ Runs a case for the project. @@ -1154,5 +1168,6 @@ def run_case( fork_from=fork_from, solver_version=solver_version, use_beta_mesher=use_beta_mesher, + **kwargs, ) return case diff --git a/flow360/component/simulation/web/draft.py b/flow360/component/simulation/web/draft.py index 0191fb747..85e8cd46e 100644 --- a/flow360/component/simulation/web/draft.py +++ b/flow360/component/simulation/web/draft.py @@ -3,11 +3,14 @@ from __future__ import annotations import json -from datetime import datetime -from typing import Annotated, Literal, Optional - -import pydantic as pd +from typing import Literal, Union +from flow360.cloud.flow360_requests import ( + DraftCreateRequest, + DraftRunRequest, + ForceCreationConfig, + IDStringType, +) from flow360.cloud.rest_api import RestApi from flow360.component.interfaces import DraftInterface from flow360.component.resource_base import ( @@ -15,39 +18,11 @@ Flow360Resource, ResourceDraft, ) -from flow360.component.utils import is_valid_uuid, validate_type +from flow360.component.utils import validate_type from flow360.exceptions import Flow360WebError from flow360.log import log -def _valid_id_validator(input_id: str): - is_valid_uuid(input_id) - return input_id - - -IDStringType = Annotated[str, pd.AfterValidator(_valid_id_validator)] - - -class DraftPostRequest(pd.BaseModel): - """Data model for draft post request""" - - name: Optional[str] = pd.Field(None) - project_id: IDStringType = pd.Field(serialization_alias="projectId") - source_item_id: IDStringType = pd.Field(serialization_alias="sourceItemId") - source_item_type: Literal[ - "Project", "Folder", "Geometry", "SurfaceMesh", "VolumeMesh", "Case", "Draft" - ] = pd.Field(serialization_alias="sourceItemType") - solver_version: str = pd.Field(serialization_alias="solverVersion") - fork_case: bool = pd.Field(serialization_alias="forkCase") - - @pd.field_validator("name", mode="after") - @classmethod - def _generate_default_name(cls, values): - if values is None: - values = "Draft " + datetime.now().strftime("%m-%d %H:%M:%S") - return values - - class DraftDraft(ResourceDraft): """ Draft Draft component @@ -65,7 +40,7 @@ def __init__( solver_version: str, fork_case: bool, ): - self._request = DraftPostRequest( + self._request = DraftCreateRequest( name=name, project_id=project_id, source_item_id=source_item_id, @@ -142,18 +117,38 @@ def get_simulation_dict(self) -> dict: response = self.get(method="simulation/file", params={"type": "simulation"}) return json.loads(response["simulationJson"]) - def run_up_to_target_asset(self, target_asset: type, use_beta_mesher: bool) -> str: + def run_up_to_target_asset( + self, + target_asset: type, + use_beta_mesher: bool, + source_item_type: Literal["Geometry", "SurfaceMesh", "VolumeMesh", "Case"], + start_from: Union[None, Literal["SurfaceMesh", "VolumeMesh", "Case"]], + ) -> str: """run the draft up to the target asset""" try: # pylint: disable=protected-access if use_beta_mesher is True: log.info("Selecting beta/in-house mesher for possible meshing tasks.") + if start_from: + if start_from != target_asset._cloud_resource_type_name: + log.info( + f"Force creating new resource(s) from {start_from} " + + f"until {target_asset._cloud_resource_type_name}" + ) + else: + log.info(f"Force creating a new {target_asset._cloud_resource_type_name}.") + force_creation_config = ( + ForceCreationConfig(start_from=start_from) if start_from else None + ) + run_request = DraftRunRequest( + source_item_type=source_item_type, + up_to=target_asset._cloud_resource_type_name, + use_in_house=use_beta_mesher, + force_creation_config=force_creation_config, + ) run_response = self.post( - json={ - "upTo": target_asset._cloud_resource_type_name, - "useInHouse": use_beta_mesher, - }, + run_request.model_dump(by_alias=True), method="run", ) destination_id = run_response["id"] diff --git a/tests/data/case-f7480884-4493-4453-9a27-dd5f8498c608/simulation.json b/tests/data/case-f7480884-4493-4453-9a27-dd5f8498c608/simulation.json new file mode 100644 index 000000000..bfb38affc --- /dev/null +++ b/tests/data/case-f7480884-4493-4453-9a27-dd5f8498c608/simulation.json @@ -0,0 +1,550 @@ +{ + "hash": "59cebdad13daabd9f3fbfec61683efc899754eba5522638012943f6b7f283e13", + "meshing": null, + "models": [ + { + "initial_condition": { + "constants": null, + "p": "p", + "rho": "rho", + "type_name": "NavierStokesInitialCondition", + "u": "u", + "v": "v", + "w": "w" + }, + "material": { + "dynamic_viscosity": { + "effective_temperature": { + "units": "K", + "value": 110.4 + }, + "reference_temperature": { + "units": "K", + "value": 273.15 + }, + "reference_viscosity": { + "units": "Pa*s", + "value": 1.716e-05 + } + }, + "name": "air", + "type": "air" + }, + "navier_stokes_solver": { + "CFL_multiplier": 1.0, + "absolute_tolerance": 1e-09, + "equation_evaluation_frequency": 1, + "kappa_MUSCL": -1.0, + "limit_pressure_density": false, + "limit_velocity": false, + "linear_solver": { + "absolute_tolerance": null, + "max_iterations": 35, + "relative_tolerance": null + }, + "low_mach_preconditioner": false, + "low_mach_preconditioner_threshold": null, + "max_force_jac_update_physical_steps": 0, + "numerical_dissipation_factor": 1.0, + "order_of_accuracy": 2, + "private_attribute_dict": null, + "relative_tolerance": 0.0, + "type_name": "Compressible", + "update_jacobian_frequency": 4 + }, + "transition_model_solver": { + "type_name": "None" + }, + "turbulence_model_solver": { + "CFL_multiplier": 2.0, + "absolute_tolerance": 1e-08, + "equation_evaluation_frequency": 4, + "hybrid_model": null, + "linear_solver": { + "absolute_tolerance": null, + "max_iterations": 25, + "relative_tolerance": null + }, + "max_force_jac_update_physical_steps": 0, + "modeling_constants": { + "C_DES": 0.72, + "C_cb1": 0.1355, + "C_cb2": 0.622, + "C_d": 8.0, + "C_min_rd": 10.0, + "C_sigma": 0.6666666666666666, + "C_t3": 1.2, + "C_t4": 0.5, + "C_v1": 7.1, + "C_vonKarman": 0.41, + "C_w2": 0.3, + "type_name": "SpalartAllmarasConsts" + }, + "order_of_accuracy": 2, + "private_attribute_dict": null, + "quadratic_constitutive_relation": false, + "reconstruction_gradient_limiter": 0.5, + "relative_tolerance": 0.0, + "rotation_correction": false, + "type_name": "SpalartAllmaras", + "update_jacobian_frequency": 4 + }, + "type": "Fluid" + }, + { + "entities": { + "stored_entities": [ + { + "axes": null, + "axis": null, + "center": null, + "name": "solid", + "private_attribute_entity_type_name": "GenericVolume", + "private_attribute_full_name": "solid", + "private_attribute_id": null, + "private_attribute_registry_bucket_name": "VolumetricEntityType", + "private_attribute_zone_boundary_names": { + "items": [ + "solid/Interface_fluid", + "solid/adiabatic" + ] + } + } + ] + }, + "heat_equation_solver": { + "absolute_tolerance": 1e-11, + "equation_evaluation_frequency": 10, + "linear_solver": { + "absolute_tolerance": 1e-12, + "max_iterations": 25, + "relative_tolerance": null + }, + "order_of_accuracy": 2, + "private_attribute_dict": null, + "relative_tolerance": 0.0, + "type_name": "HeatEquation" + }, + "initial_condition": null, + "material": { + "density": null, + "name": "copper", + "specific_heat_capacity": null, + "thermal_conductivity": { + "units": "W/(K*m)", + "value": 398.0 + }, + "type": "solid" + }, + "name": null, + "type": "Solid", + "volumetric_heat_source": { + "units": "W/m**3", + "value": 397772.4741447892 + } + }, + { + "entities": { + "stored_entities": [ + { + "name": "fluid/centerbody", + "private_attribute_entity_type_name": "Surface", + "private_attribute_full_name": "fluid/centerbody", + "private_attribute_id": null, + "private_attribute_is_interface": false, + "private_attribute_registry_bucket_name": "SurfaceEntityType", + "private_attribute_sub_components": [], + "private_attribute_tag_key": null + } + ] + }, + "heat_spec": { + "type_name": "HeatFlux", + "value": { + "units": "W/m**2", + "value": 0.0 + } + }, + "name": null, + "roughness_height": { + "units": "m", + "value": 0.0 + }, + "type": "Wall", + "use_wall_function": false, + "velocity": null + }, + { + "entities": { + "stored_entities": [ + { + "name": "fluid/farfield", + "private_attribute_entity_type_name": "Surface", + "private_attribute_full_name": "fluid/farfield", + "private_attribute_id": null, + "private_attribute_is_interface": false, + "private_attribute_registry_bucket_name": "SurfaceEntityType", + "private_attribute_sub_components": [], + "private_attribute_tag_key": null + } + ] + }, + "name": null, + "turbulence_quantities": null, + "type": "Freestream", + "velocity": null + }, + { + "entities": { + "stored_entities": [ + { + "name": "solid/adiabatic", + "private_attribute_entity_type_name": "Surface", + "private_attribute_full_name": "solid/adiabatic", + "private_attribute_id": null, + "private_attribute_is_interface": false, + "private_attribute_registry_bucket_name": "SurfaceEntityType", + "private_attribute_sub_components": [], + "private_attribute_tag_key": null + } + ] + }, + "heat_spec": { + "type_name": "HeatFlux", + "value": { + "units": "W/m**2", + "value": 0.0 + } + }, + "name": null, + "roughness_height": { + "units": "m", + "value": 0.0 + }, + "type": "Wall", + "use_wall_function": false, + "velocity": null + } + ], + "operating_condition": { + "alpha": { + "units": "degree", + "value": 0.0 + }, + "beta": { + "units": "degree", + "value": 0.0 + }, + "private_attribute_constructor": "from_mach", + "private_attribute_input_cache": { + "alpha": { + "units": "degree", + "value": 0.0 + }, + "beta": { + "units": "degree", + "value": 0.0 + }, + "mach": 0.1, + "reference_mach": null, + "thermal_state": { + "density": { + "units": "kg/m**3", + "value": 1.225 + }, + "material": { + "dynamic_viscosity": { + "effective_temperature": { + "units": "K", + "value": 110.4 + }, + "reference_temperature": { + "units": "K", + "value": 273.15 + }, + "reference_viscosity": { + "units": "Pa*s", + "value": 1.716e-05 + } + }, + "name": "air", + "type": "air" + }, + "private_attribute_constructor": "default", + "private_attribute_input_cache": { + "altitude": null, + "temperature_offset": null + }, + "temperature": { + "units": "K", + "value": 288.15 + }, + "type_name": "ThermalState" + } + }, + "reference_velocity_magnitude": null, + "thermal_state": { + "density": { + "units": "kg/m**3", + "value": 1.225 + }, + "material": { + "dynamic_viscosity": { + "effective_temperature": { + "units": "K", + "value": 110.4 + }, + "reference_temperature": { + "units": "K", + "value": 273.15 + }, + "reference_viscosity": { + "units": "Pa*s", + "value": 1.716e-05 + } + }, + "name": "air", + "type": "air" + }, + "private_attribute_constructor": "default", + "private_attribute_input_cache": { + "altitude": null, + "temperature_offset": null + }, + "temperature": { + "units": "K", + "value": 288.15 + }, + "type_name": "ThermalState" + }, + "type_name": "AerospaceCondition", + "velocity_magnitude": { + "units": "m/s", + "value": 34.02940058082128 + } + }, + "outputs": [ + { + "frequency": -1, + "frequency_offset": 0, + "name": "fl.VolumeOutput", + "output_fields": { + "items": [ + "primitiveVars", + "T", + "Cp", + "Mach" + ] + }, + "output_format": "both", + "output_type": "VolumeOutput" + }, + { + "entities": { + "stored_entities": [ + { + "name": "fluid/farfield", + "private_attribute_entity_type_name": "Surface", + "private_attribute_full_name": "fluid/farfield", + "private_attribute_id": null, + "private_attribute_is_interface": false, + "private_attribute_registry_bucket_name": "SurfaceEntityType", + "private_attribute_sub_components": [], + "private_attribute_tag_key": null + }, + { + "name": "solid/Interface_fluid", + "private_attribute_entity_type_name": "Surface", + "private_attribute_full_name": "solid/Interface_fluid", + "private_attribute_id": null, + "private_attribute_is_interface": true, + "private_attribute_registry_bucket_name": "SurfaceEntityType", + "private_attribute_sub_components": [], + "private_attribute_tag_key": null + }, + { + "name": "fluid/centerbody", + "private_attribute_entity_type_name": "Surface", + "private_attribute_full_name": "fluid/centerbody", + "private_attribute_id": null, + "private_attribute_is_interface": false, + "private_attribute_registry_bucket_name": "SurfaceEntityType", + "private_attribute_sub_components": [], + "private_attribute_tag_key": null + }, + { + "name": "solid/adiabatic", + "private_attribute_entity_type_name": "Surface", + "private_attribute_full_name": "solid/adiabatic", + "private_attribute_id": null, + "private_attribute_is_interface": false, + "private_attribute_registry_bucket_name": "SurfaceEntityType", + "private_attribute_sub_components": [], + "private_attribute_tag_key": null + }, + { + "name": "fluid/Interface_solid", + "private_attribute_entity_type_name": "Surface", + "private_attribute_full_name": "fluid/Interface_solid", + "private_attribute_id": null, + "private_attribute_is_interface": true, + "private_attribute_registry_bucket_name": "SurfaceEntityType", + "private_attribute_sub_components": [], + "private_attribute_tag_key": null + } + ] + }, + "frequency": -1, + "frequency_offset": 0, + "name": "fl.SurfaceOutput", + "output_fields": { + "items": [ + "primitiveVars", + "T", + "Cp", + "Cf", + "CfVec" + ] + }, + "output_format": "both", + "output_type": "SurfaceOutput", + "write_single_file": false + } + ], + "private_attribute_asset_cache": { + "project_entity_info": { + "boundaries": [ + { + "name": "fluid/farfield", + "private_attribute_entity_type_name": "Surface", + "private_attribute_full_name": "fluid/farfield", + "private_attribute_id": null, + "private_attribute_is_interface": false, + "private_attribute_registry_bucket_name": "SurfaceEntityType", + "private_attribute_sub_components": [], + "private_attribute_tag_key": null + }, + { + "name": "solid/Interface_fluid", + "private_attribute_entity_type_name": "Surface", + "private_attribute_full_name": "solid/Interface_fluid", + "private_attribute_id": null, + "private_attribute_is_interface": true, + "private_attribute_registry_bucket_name": "SurfaceEntityType", + "private_attribute_sub_components": [], + "private_attribute_tag_key": null + }, + { + "name": "fluid/centerbody", + "private_attribute_entity_type_name": "Surface", + "private_attribute_full_name": "fluid/centerbody", + "private_attribute_id": null, + "private_attribute_is_interface": false, + "private_attribute_registry_bucket_name": "SurfaceEntityType", + "private_attribute_sub_components": [], + "private_attribute_tag_key": null + }, + { + "name": "solid/adiabatic", + "private_attribute_entity_type_name": "Surface", + "private_attribute_full_name": "solid/adiabatic", + "private_attribute_id": null, + "private_attribute_is_interface": false, + "private_attribute_registry_bucket_name": "SurfaceEntityType", + "private_attribute_sub_components": [], + "private_attribute_tag_key": null + }, + { + "name": "fluid/Interface_solid", + "private_attribute_entity_type_name": "Surface", + "private_attribute_full_name": "fluid/Interface_solid", + "private_attribute_id": null, + "private_attribute_is_interface": true, + "private_attribute_registry_bucket_name": "SurfaceEntityType", + "private_attribute_sub_components": [], + "private_attribute_tag_key": null + } + ], + "draft_entities": [], + "ghost_entities": [], + "type_name": "VolumeMeshEntityInfo", + "zones": [ + { + "axes": null, + "axis": null, + "center": null, + "name": "fluid", + "private_attribute_entity_type_name": "GenericVolume", + "private_attribute_full_name": "fluid", + "private_attribute_id": null, + "private_attribute_registry_bucket_name": "VolumetricEntityType", + "private_attribute_zone_boundary_names": { + "items": [ + "fluid/Interface_solid", + "fluid/centerbody", + "fluid/farfield" + ] + } + }, + { + "axes": null, + "axis": null, + "center": null, + "name": "solid", + "private_attribute_entity_type_name": "GenericVolume", + "private_attribute_full_name": "solid", + "private_attribute_id": null, + "private_attribute_registry_bucket_name": "VolumetricEntityType", + "private_attribute_zone_boundary_names": { + "items": [ + "solid/Interface_fluid", + "solid/adiabatic" + ] + } + } + ] + }, + "project_length_unit": { + "units": "m", + "value": 1.0 + } + }, + "reference_geometry": { + "area": { + "units": "m**2", + "value": 1.0 + }, + "moment_center": { + "units": "m", + "value": [ + 0.0, + 0.0, + 0.0 + ] + }, + "moment_length": { + "units": "m", + "value": [ + 1.0, + 1.0, + 1.0 + ] + } + }, + "time_stepping": { + "CFL": { + "final": 100.0, + "initial": 1.0, + "ramp_steps": 1000, + "type": "ramp" + }, + "max_steps": 10000, + "type_name": "Steady" + }, + "unit_system": { + "name": "SI" + }, + "user_defined_dynamics": null, + "user_defined_fields": [], + "version": "25.2.1" +} \ No newline at end of file diff --git a/tests/data/mock_webapi/project_from_vm_case_meta_resp.json b/tests/data/mock_webapi/project_from_vm_case_meta_resp.json new file mode 100644 index 000000000..d41ae7738 --- /dev/null +++ b/tests/data/mock_webapi/project_from_vm_case_meta_resp.json @@ -0,0 +1,86 @@ +{ + "data": { + "caseId": "case-f7480884-4493-4453-9a27-dd5f8498c608", + "caseMeshId": "vm-bff35714-41b1-4251-ac74-46a40b95a330", + "caseName": "Tutorial CHT Solver from Python", + "casePriority": null, + "caseStatus": "completed", + "caseStartTime": "2025-02-26T19:41:50.761Z", + "caseSubmitTime": "2025-02-26T19:41:32.906Z", + "caseFinishTime": "2025-02-26T19:55:22.232Z", + "caseParentId": null, + "userId": "AIDAXWCOWJGJJBXX543AQ", + "caseTags": null, + "meshSize": 0, + "nodesInfo": null, + "solverVersion": "release-25.2.1", + "userEmail": "auto_test_1@flexcompute.com", + "estimationDuration": 0.0, + "meshNodeSize": 2417400, + "realFlexUnit": 2.4079200000000003, + "estWorkUnit": 2.4079200000000003, + "storageSize": 391820719, + "storageStatus": "STANDARD", + "standardAge": 1, + "storageClass": "STANDARD", + "restoreAt": null, + "deleted": false, + "errorType": null, + "retryCount": "0", + "supportStorageSize": 454309757, + "oriRealFlexUnit": 2.4079200000000003, + "clonedFrom": null, + "updatedAt": "2025-02-26T20:03:06.662Z", + "currentProgress": { + "Type": "flow360_case", + "Percentage": "100.0", + "Stage": "case visualization", + "Time": "2025-02-26T19:56:00.171Z", + "Id": "case-f7480884-4493-4453-9a27-dd5f8498c608", + "Source": "progress.csv" + }, + "events": null, + "exampleResource": false, + "parentFolders": [ + { + "userId": "AIDAXWCOWJGJJBXX543AQ", + "name": "ROOT.FLOW360", + "tags": null, + "id": "ROOT.FLOW360", + "parentFolderId": null, + "createdAt": "2023-09-01T09:14:15.293797Z", + "updatedAt": "2023-09-01T09:14:15.293797Z" + }, + { + "userId": "AIDAXWCOWJGJJBXX543AQ", + "name": "angran", + "tags": null, + "id": "folder-96c1461e-e3c4-4b44-9f0e-5b4ec3a23777", + "parentFolderId": "ROOT.FLOW360", + "createdAt": "2024-10-18T18:34:13.241543Z", + "updatedAt": "2024-10-18T18:34:13.241543Z" + } + ], + "parentFolderId": "folder-96c1461e-e3c4-4b44-9f0e-5b4ec3a23777", + "projectId": "prj-99cc6f96-15d3-4170-973c-a0cced6bf36b", + "viewed": true, + "unitSystem": null, + "name": "Tutorial CHT Solver from Python", + "id": "case-f7480884-4493-4453-9a27-dd5f8498c608", + "internal": false, + "success": true, + "status": "completed", + "highPriority": false, + "parentId": null, + "estFlexUnit": 2.4079200000000003, + "refId": "vm-bff35714-41b1-4251-ac74-46a40b95a330", + "userDataUploaded": null, + "combinedStatus": "completed", + "objectRefId": "case-f7480884-4493-4453-9a27-dd5f8498c608", + "metadataProcessed": false, + "nodeSize": 0, + "computeCost": 2.4079200000000003, + "elapsedTimeInSeconds": 811, + "running": false + } +} \ No newline at end of file diff --git a/tests/data/mock_webapi/project_from_vm_get_tree_resp.json b/tests/data/mock_webapi/project_from_vm_get_tree_resp.json new file mode 100644 index 000000000..f0529e5c3 --- /dev/null +++ b/tests/data/mock_webapi/project_from_vm_get_tree_resp.json @@ -0,0 +1,84 @@ +{ + "data": { + "records": [ + { + "userId": "AIDAXWCOWJGJJBXX543AQ", + "id": "vm-bff35714-41b1-4251-ac74-46a40b95a330", + "name": "Tutorial CHT Solver from Python", + "type": "VolumeMesh", + "projectId": "prj-99cc6f96-15d3-4170-973c-a0cced6bf36b", + "parentFolderId": "folder-96c1461e-e3c4-4b44-9f0e-5b4ec3a23777", + "tags": null, + "status": "completed", + "parentId": null, + "parentCaseId": null, + "visualizationStatus": "completed", + "postProcessStatus": null, + "solverVersion": "release-25.2.1", + "viewed": false, + "deleted": false, + "solverStartAt": null, + "solverFinishAt": null, + "runSequence": "run-24d06899-d975-411c-9e10-76248ed548ec", + "createdAt": "2025-02-26T19:40:45.645Z", + "updatedAt": "2025-02-26T19:42:30.894Z", + "visualizedAt": null, + "postProcessedAt": null, + "requestStopAt": null, + "interpolated": false, + "companionParentItemType": null, + "parentItemProjectId": null, + "parentItemProjectName": null, + "parentItemName": null, + "parentItemDeleted": false, + "parentItemType": null, + "parentCaseProjectId": null, + "parentCaseProjectName": null, + "parentCaseName": null, + "parentCaseDeleted": false, + "parentCaseType": null, + "displayStatus": "completed", + "solverUpdatedAt": "2025-02-26T19:42:30.894Z" + }, + { + "userId": "AIDAXWCOWJGJJBXX543AQ", + "id": "case-f7480884-4493-4453-9a27-dd5f8498c608", + "name": "Tutorial CHT Solver from Python", + "type": "Case", + "projectId": "prj-99cc6f96-15d3-4170-973c-a0cced6bf36b", + "parentFolderId": "folder-96c1461e-e3c4-4b44-9f0e-5b4ec3a23777", + "tags": null, + "status": "completed", + "parentId": "vm-bff35714-41b1-4251-ac74-46a40b95a330", + "parentCaseId": null, + "visualizationStatus": "completed", + "postProcessStatus": "completed", + "solverVersion": "release-25.2.1", + "viewed": true, + "deleted": false, + "solverStartAt": "2025-02-26T19:41:50.761Z", + "solverFinishAt": "2025-02-26T19:55:22.232Z", + "runSequence": "run-88d8048b-e6bb-4d2d-b7b2-7fc130ea38fb", + "createdAt": "2025-02-26T19:41:32.906Z", + "updatedAt": "2025-02-26T20:03:06.662Z", + "visualizedAt": "2025-02-26T19:56:04.814Z", + "postProcessedAt": "2025-02-26T19:55:28.093Z", + "requestStopAt": null, + "interpolated": false, + "companionParentItemType": "Case", + "parentItemProjectId": "prj-99cc6f96-15d3-4170-973c-a0cced6bf36b", + "parentItemProjectName": "Tutorial CHT Solver from Python", + "parentItemName": "Tutorial CHT Solver from Python", + "parentItemDeleted": false, + "parentItemType": "VolumeMesh", + "parentCaseProjectId": null, + "parentCaseProjectName": null, + "parentCaseName": null, + "parentCaseDeleted": false, + "parentCaseType": null, + "displayStatus": "completed", + "solverUpdatedAt": "2025-02-26T19:55:22.232Z" + } + ] + } +} \ No newline at end of file diff --git a/tests/data/mock_webapi/project_from_vm_meta_resp.json b/tests/data/mock_webapi/project_from_vm_meta_resp.json new file mode 100644 index 000000000..c15ae629a --- /dev/null +++ b/tests/data/mock_webapi/project_from_vm_meta_resp.json @@ -0,0 +1,74 @@ +{ + "data": { + "userId": "AIDAXWCOWJGJJBXX543AQ", + "id": "prj-99cc6f96-15d3-4170-973c-a0cced6bf36b", + "name": "Tutorial CHT Solver from Python", + "tags": [], + "parentFolderId": "folder-96c1461e-e3c4-4b44-9f0e-5b4ec3a23777", + "deleted": false, + "description": "", + "icon": null, + "statistics": { + "Case": { + "count": 1, + "successCount": 1, + "runningCount": 0, + "divergedCount": 0, + "errorCount": 0 + }, + "VolumeMesh": { + "count": 1, + "successCount": 1, + "runningCount": 0, + "divergedCount": 0, + "errorCount": 0 + } + }, + "solverVersion": "release-25.2.1", + "parentFolders": [ + { + "type": "Folder", + "userId": "AIDAXWCOWJGJJBXX543AQ", + "name": "ROOT.FLOW360", + "tags": [], + "id": "ROOT.FLOW360", + "parentFolderId": null, + "parentFolders": null, + "createdAt": "2023-09-01T09:14:15.293797Z", + "updatedAt": "2023-09-01T09:14:15.293797Z" + }, + { + "type": "Folder", + "userId": "AIDAXWCOWJGJJBXX543AQ", + "name": "angran", + "tags": [], + "id": "folder-96c1461e-e3c4-4b44-9f0e-5b4ec3a23777", + "parentFolderId": "ROOT.FLOW360", + "parentFolders": null, + "createdAt": "2024-10-18T18:34:13.241543Z", + "updatedAt": "2024-10-18T18:34:13.241543Z" + } + ], + "viewed": true, + "lastOpenDraftId": "dft-42dcdc04-52f5-4b18-8c46-80fb74fb2cc2", + "lastOpenItemId": "case-f7480884-4493-4453-9a27-dd5f8498c608", + "lastOpenItemType": "Case", + "latestItemId": "case-f7480884-4493-4453-9a27-dd5f8498c608", + "latestItemType": "Case", + "rootItemId": "vm-bff35714-41b1-4251-ac74-46a40b95a330", + "rootItemType": "VolumeMesh", + "createdAt": "2025-02-26T19:40:46.067988Z", + "updatedAt": "2025-02-27T16:52:56.984Z", + "createdBy": "AIDAXWCOWJGJJBXX543AQ", + "updatedBy": "AIDAXWCOWJGJJBXX543AQ", + "canOpen": true, + "rootItemStatus": "completed", + "rootItemUploadedAt": "2025-02-26T19:41:02.613Z", + "rootItemVisualizationStatus": "completed", + "rootItemUploadStatus": "success", + "copyStatus": "notCopy", + "copyFromResourceCount": 0, + "copiedResourceCount": 0, + "rootItemDisplayStatus": "completed" + } +} \ No newline at end of file diff --git a/tests/data/mock_webapi/project_from_vm_volume_mesh_meta_resp.json b/tests/data/mock_webapi/project_from_vm_volume_mesh_meta_resp.json new file mode 100644 index 000000000..23ad3e726 --- /dev/null +++ b/tests/data/mock_webapi/project_from_vm_volume_mesh_meta_resp.json @@ -0,0 +1,50 @@ +{ + "data": { + "type": "VolumeMesh", + "userId": "AIDAXWCOWJGJJBXX543AQ", + "id": "vm-bff35714-41b1-4251-ac74-46a40b95a330", + "parentId": null, + "name": "Tutorial CHT Solver from Python", + "tags": [], + "status": "completed", + "visualizationStatus": "completed", + "solverVersion": "release-25.2.1", + "parentFolderId": "folder-96c1461e-e3c4-4b44-9f0e-5b4ec3a23777", + "projectId": "prj-99cc6f96-15d3-4170-973c-a0cced6bf36b", + "viewed": null, + "parentFolders": [ + { + "type": "Folder", + "userId": "AIDAXWCOWJGJJBXX543AQ", + "name": "ROOT.FLOW360", + "tags": [], + "id": "ROOT.FLOW360", + "parentFolderId": null, + "parentFolders": null, + "createdAt": "2023-09-01T09:14:15.293797Z", + "updatedAt": "2023-09-01T09:14:15.293797Z" + }, + { + "type": "Folder", + "userId": "AIDAXWCOWJGJJBXX543AQ", + "name": "angran", + "tags": [], + "id": "folder-96c1461e-e3c4-4b44-9f0e-5b4ec3a23777", + "parentFolderId": "ROOT.FLOW360", + "parentFolders": null, + "createdAt": "2024-10-18T18:34:13.241543Z", + "updatedAt": "2024-10-18T18:34:13.241543Z" + } + ], + "storageSize": 113058078, + "deleted": false, + "createdAt": "2025-02-26T19:40:45.645Z", + "updatedAt": "2025-02-26T19:42:30.894Z", + "uploadStatus": "success", + "format": "cgns", + "nodeInfo": null, + "storageStatus": null, + "fileName": "volumeMesh.cgns.zst", + "displayStatus": "completed" + } +} \ No newline at end of file diff --git a/tests/data/mock_webapi/project_from_vm_volume_mesh_simulation_json_resp.json b/tests/data/mock_webapi/project_from_vm_volume_mesh_simulation_json_resp.json new file mode 100644 index 000000000..6f896b103 --- /dev/null +++ b/tests/data/mock_webapi/project_from_vm_volume_mesh_simulation_json_resp.json @@ -0,0 +1,5 @@ +{ + "data": { + "simulationJson": "{\"version\": \"25.2.1\", \"unit_system\": {\"name\": \"SI\"}, \"reference_geometry\": {\"moment_center\": {\"value\": [0.0, 0.0, 0.0], \"units\": \"m\"}, \"moment_length\": {\"value\": [1.0, 1.0, 1.0], \"units\": \"m\"}, \"area\": {\"value\": 1.0, \"units\": \"m**2\"}}, \"operating_condition\": {\"type_name\": \"AerospaceCondition\", \"private_attribute_constructor\": \"default\", \"private_attribute_input_cache\": {\"alpha\": {\"value\": 0.0, \"units\": \"degree\"}, \"beta\": {\"value\": 0.0, \"units\": \"degree\"}, \"thermal_state\": {\"type_name\": \"ThermalState\", \"private_attribute_constructor\": \"default\", \"private_attribute_input_cache\": {}, \"temperature\": {\"value\": 288.15, \"units\": \"K\"}, \"density\": {\"value\": 1.225, \"units\": \"kg/m**3\"}, \"material\": {\"type\": \"air\", \"name\": \"air\", \"dynamic_viscosity\": {\"reference_viscosity\": {\"value\": 1.716e-05, \"units\": \"Pa*s\"}, \"reference_temperature\": {\"value\": 273.15, \"units\": \"K\"}, \"effective_temperature\": {\"value\": 110.4, \"units\": \"K\"}}}}}, \"alpha\": {\"value\": 0.0, \"units\": \"degree\"}, \"beta\": {\"value\": 0.0, \"units\": \"degree\"}, \"thermal_state\": {\"type_name\": \"ThermalState\", \"private_attribute_constructor\": \"default\", \"private_attribute_input_cache\": {}, \"temperature\": {\"value\": 288.15, \"units\": \"K\"}, \"density\": {\"value\": 1.225, \"units\": \"kg/m**3\"}, \"material\": {\"type\": \"air\", \"name\": \"air\", \"dynamic_viscosity\": {\"reference_viscosity\": {\"value\": 1.716e-05, \"units\": \"Pa*s\"}, \"reference_temperature\": {\"value\": 273.15, \"units\": \"K\"}, \"effective_temperature\": {\"value\": 110.4, \"units\": \"K\"}}}}}, \"models\": [{\"type\": \"Wall\", \"entities\": {\"stored_entities\": []}, \"name\": \"Wall\", \"use_wall_function\": false, \"heat_spec\": {\"value\": {\"value\": 0.0, \"units\": \"W/m**2\"}, \"type_name\": \"HeatFlux\"}, \"roughness_height\": {\"value\": 0.0, \"units\": \"m\"}}, {\"type\": \"Freestream\", \"entities\": {\"stored_entities\": []}, \"name\": \"Freestream\"}, {\"material\": {\"type\": \"air\", \"name\": \"air\", \"dynamic_viscosity\": {\"reference_viscosity\": {\"value\": 1.716e-05, \"units\": \"Pa*s\"}, \"reference_temperature\": {\"value\": 273.15, \"units\": \"K\"}, \"effective_temperature\": {\"value\": 110.4, \"units\": \"K\"}}}, \"initial_condition\": {\"type_name\": \"NavierStokesInitialCondition\", \"rho\": \"rho\", \"u\": \"u\", \"v\": \"v\", \"w\": \"w\", \"p\": \"p\"}, \"type\": \"Fluid\", \"navier_stokes_solver\": {\"absolute_tolerance\": 1e-10, \"relative_tolerance\": 0.0, \"order_of_accuracy\": 2, \"equation_evaluation_frequency\": 1, \"linear_solver\": {\"max_iterations\": 30}, \"CFL_multiplier\": 1.0, \"kappa_MUSCL\": -1.0, \"numerical_dissipation_factor\": 1.0, \"limit_velocity\": false, \"limit_pressure_density\": false, \"type_name\": \"Compressible\", \"low_mach_preconditioner\": false, \"update_jacobian_frequency\": 4, \"max_force_jac_update_physical_steps\": 0}, \"turbulence_model_solver\": {\"absolute_tolerance\": 1e-08, \"relative_tolerance\": 0.0, \"order_of_accuracy\": 2, \"equation_evaluation_frequency\": 4, \"linear_solver\": {\"max_iterations\": 20}, \"CFL_multiplier\": 2.0, \"type_name\": \"SpalartAllmaras\", \"reconstruction_gradient_limiter\": 0.5, \"quadratic_constitutive_relation\": false, \"modeling_constants\": {\"type_name\": \"SpalartAllmarasConsts\", \"C_DES\": 0.72, \"C_d\": 8.0, \"C_cb1\": 0.1355, \"C_cb2\": 0.622, \"C_sigma\": 0.6666666666666666, \"C_v1\": 7.1, \"C_vonKarman\": 0.41, \"C_w2\": 0.3, \"C_t3\": 1.2, \"C_t4\": 0.5, \"C_min_rd\": 10.0}, \"update_jacobian_frequency\": 4, \"max_force_jac_update_physical_steps\": 0, \"rotation_correction\": false}, \"transition_model_solver\": {\"type_name\": \"None\"}}], \"time_stepping\": {\"type_name\": \"Steady\", \"max_steps\": 2000, \"CFL\": {\"type\": \"adaptive\", \"min\": 0.1, \"max\": 10000.0, \"max_relative_change\": 1.0, \"convergence_limiting_factor\": 0.25}}, \"user_defined_fields\": [], \"outputs\": [{\"frequency\": -1, \"frequency_offset\": 0, \"output_format\": \"paraview\", \"name\": \"Surface output\", \"entities\": {\"stored_entities\": [{\"private_attribute_registry_bucket_name\": \"SurfaceEntityType\", \"private_attribute_entity_type_name\": \"Surface\", \"name\": \"*\", \"private_attribute_sub_components\": []}]}, \"write_single_file\": false, \"output_fields\": {\"items\": [\"Cp\", \"yPlus\", \"Cf\", \"CfVec\"]}, \"output_type\": \"SurfaceOutput\"}], \"private_attribute_asset_cache\": {\"project_length_unit\": {\"value\": 1.0, \"units\": \"m\"}, \"project_entity_info\": {\"type_name\": \"VolumeMeshEntityInfo\", \"zones\": [{\"private_attribute_registry_bucket_name\": \"VolumetricEntityType\", \"private_attribute_entity_type_name\": \"GenericVolume\", \"private_attribute_id\": null, \"name\": \"fluid\", \"private_attribute_zone_boundary_names\": {\"items\": [\"fluid/Interface_solid\", \"fluid/centerbody\", \"fluid/farfield\"]}, \"private_attribute_full_name\": \"fluid\", \"axes\": null, \"axis\": null, \"center\": null}, {\"private_attribute_registry_bucket_name\": \"VolumetricEntityType\", \"private_attribute_entity_type_name\": \"GenericVolume\", \"private_attribute_id\": null, \"name\": \"solid\", \"private_attribute_zone_boundary_names\": {\"items\": [\"solid/Interface_fluid\", \"solid/adiabatic\"]}, \"private_attribute_full_name\": \"solid\", \"axes\": null, \"axis\": null, \"center\": null}], \"boundaries\": [{\"private_attribute_registry_bucket_name\": \"SurfaceEntityType\", \"private_attribute_entity_type_name\": \"Surface\", \"private_attribute_id\": null, \"name\": \"fluid/farfield\", \"private_attribute_full_name\": \"fluid/farfield\", \"private_attribute_is_interface\": false, \"private_attribute_tag_key\": null, \"private_attribute_sub_components\": []}, {\"private_attribute_registry_bucket_name\": \"SurfaceEntityType\", \"private_attribute_entity_type_name\": \"Surface\", \"private_attribute_id\": null, \"name\": \"solid/Interface_fluid\", \"private_attribute_full_name\": \"solid/Interface_fluid\", \"private_attribute_is_interface\": true, \"private_attribute_tag_key\": null, \"private_attribute_sub_components\": []}, {\"private_attribute_registry_bucket_name\": \"SurfaceEntityType\", \"private_attribute_entity_type_name\": \"Surface\", \"private_attribute_id\": null, \"name\": \"fluid/centerbody\", \"private_attribute_full_name\": \"fluid/centerbody\", \"private_attribute_is_interface\": false, \"private_attribute_tag_key\": null, \"private_attribute_sub_components\": []}, {\"private_attribute_registry_bucket_name\": \"SurfaceEntityType\", \"private_attribute_entity_type_name\": \"Surface\", \"private_attribute_id\": null, \"name\": \"solid/adiabatic\", \"private_attribute_full_name\": \"solid/adiabatic\", \"private_attribute_is_interface\": false, \"private_attribute_tag_key\": null, \"private_attribute_sub_components\": []}, {\"private_attribute_registry_bucket_name\": \"SurfaceEntityType\", \"private_attribute_entity_type_name\": \"Surface\", \"private_attribute_id\": null, \"name\": \"fluid/Interface_solid\", \"private_attribute_full_name\": \"fluid/Interface_solid\", \"private_attribute_is_interface\": true, \"private_attribute_tag_key\": null, \"private_attribute_sub_components\": []}]}}}" + } +} \ No newline at end of file diff --git a/tests/mock_server.py b/tests/mock_server.py index ce20f0394..b7393e757 100644 --- a/tests/mock_server.py +++ b/tests/mock_server.py @@ -259,6 +259,16 @@ def json(): return res +class MockResponseProjectFromVM(MockResponse): + """response for Project.from_cloud(id="prj-99cc6f96-15d3-4170-973c-a0cced6bf36b")'s meta json""" + + @staticmethod + def json(): + with open(os.path.join(here, "data/mock_webapi/project_from_vm_meta_resp.json")) as fh: + res = json.load(fh) + return res + + class MockResponseAllProjects(MockResponse): """response of projects get""" @@ -279,6 +289,16 @@ def json(): return res +class MockResponseProjectFromVMTree(MockResponse): + """response for Project.from_cloud(id="prj-99cc6f96-15d3-4170-973c-a0cced6bf36b")'s tree json""" + + @staticmethod + def json(): + with open(os.path.join(here, "data/mock_webapi/project_from_vm_get_tree_resp.json")) as fh: + res = json.load(fh) + return res + + class MockResponseProjectGeometry(MockResponse): """response for Geometry.from_cloud(id="geo-2877e124-96ff-473d-864b-11eec8648d42")'s meta json""" @@ -345,6 +365,32 @@ def json(): return res +class MockResponseProjectFromVMVolumeMeshMeta(MockResponse): + """response for VolumeMesh.from_cloud(id="vm-bff35714-41b1-4251-ac74-46a40b95a330")'s meta json""" + + @staticmethod + def json(): + with open( + os.path.join(here, "data/mock_webapi/project_from_vm_volume_mesh_meta_resp.json") + ) as fh: + res = json.load(fh) + return res + + +class MockResponseProjectFromVMVolumeMeshSimConfig(MockResponse): + """response for VolumeMesh.from_cloud(id="vm-bff35714-41b1-4251-ac74-46a40b95a330")'s simualtion json""" + + @staticmethod + def json(): + with open( + os.path.join( + here, "data/mock_webapi/project_from_vm_volume_mesh_simulation_json_resp.json" + ) + ) as fh: + res = json.load(fh) + return res + + class MockResponseProjectCase(MockResponse): """response for Case.from_cloud(id="case-69b8c249-fce5-412a-9927-6a79049deebb")'s meta json""" @@ -355,6 +401,16 @@ def json(): return res +class MockResponseProjectFromVMCase(MockResponse): + """response for Case.from_cloud(id="case-f7480884-4493-4453-9a27-dd5f8498c608")'s meta json""" + + @staticmethod + def json(): + with open(os.path.join(here, "data/mock_webapi/project_from_vm_case_meta_resp.json")) as fh: + res = json.load(fh) + return res + + class MockResponseProjectCaseFork(MockResponse): """response for Case.from_cloud(id="case-69b8c249-fce5-412a-9927-6a79049deebb")'s meta json""" @@ -487,15 +543,20 @@ def json(self): "/folders/items/folder-3834758b-3d39-4a4a-ad85-710b7652267c/metadata": MockResponseFolderRootMetadata, "/folders/items/folder-4da3cdd0-c5b6-4130-9ca1-196237322ab9/metadata": MockResponseFolderNestedMetadata, "/v2/projects/prj-41d2333b-85fd-4bed-ae13-15dcb6da519e": MockResponseProject, + "/v2/projects/prj-99cc6f96-15d3-4170-973c-a0cced6bf36b": MockResponseProjectFromVM, "/v2/projects/prj-41d2333b-85fd-4bed-ae13-15dcb6da519e/tree": MockResponseProjectTree, + "/v2/projects/prj-99cc6f96-15d3-4170-973c-a0cced6bf36b/tree": MockResponseProjectFromVMTree, "/v2/geometries/geo-2877e124-96ff-473d-864b-11eec8648d42": MockResponseProjectGeometry, "/v2/geometries/geo-2877e124-96ff-473d-864b-11eec8648d42/simulation/file": MockResponseProjectGeometrySimConfig, "/v2/surface-meshes/sm-1f1f2753-fe31-47ea-b3ab-efb2313ab65a": MockResponseProjectSurfaceMesh, "/v2/surface-meshes/sm-1f1f2753-fe31-47ea-b3ab-efb2313ab65a/simulation/file": MockResponseProjectSurfaceMeshSimConfig, "/v2/volume-meshes/vm-7c3681cd-8c6c-4db7-a62c-1742d825e9d3": MockResponseProjectVolumeMesh, "/v2/volume-meshes/vm-7c3681cd-8c6c-4db7-a62c-1742d825e9d3/simulation/file": MockResponseProjectVolumeMeshSimConfig, + "/v2/volume-meshes/vm-bff35714-41b1-4251-ac74-46a40b95a330": MockResponseProjectFromVMVolumeMeshMeta, + "/v2/volume-meshes/vm-bff35714-41b1-4251-ac74-46a40b95a330/simulation/file": MockResponseProjectFromVMVolumeMeshSimConfig, "/cases/case-69b8c249-fce5-412a-9927-6a79049deebb": MockResponseProjectCase, "/v2/cases/case-69b8c249-fce5-412a-9927-6a79049deebb/simulation/file": MockResponseProjectCaseSimConfig, + "/cases/case-f7480884-4493-4453-9a27-dd5f8498c608": MockResponseProjectFromVMCase, "/cases/case-84d4604e-f3cd-4c6b-8517-92a80a3346d3": MockResponseProjectCaseFork, "/v2/cases/case-84d4604e-f3cd-4c6b-8517-92a80a3346d3/simulation/file": MockResponseProjectCaseForkSimConfig, "/v2/projects": MockResponseAllProjects, diff --git a/tests/test_project.py b/tests/test_project.py index 42581a164..902abe9c8 100644 --- a/tests/test_project.py +++ b/tests/test_project.py @@ -99,3 +99,24 @@ def test_run(mock_response, capsys): captured_text = capsys.readouterr().out captured_text = " ".join(captured_text.split()) assert warning_msg in captured_text + + error_msg = r"Input should be 'SurfaceMesh', 'VolumeMesh' or 'Case'" + with pytest.raises(pd.ValidationError, match=error_msg): + project.generate_volume_mesh(params=params, start_from="Geometry") + + error_msg = ( + r"Invalid force creation configuration: 'start_from' \(Case\) " + r"cannot be later than 'up_to' \(VolumeMesh\)." + ) + with pytest.raises(ValueError, match=error_msg): + project.generate_volume_mesh(params=params, start_from="Case") + + project_vm = fl.Project.from_cloud(project_id="prj-99cc6f96-15d3-4170-973c-a0cced6bf36b") + params = project_vm.case.params + + error_msg = ( + r"Invalid force creation configuration: 'start_from' \(SurfaceMesh\) " + r"must be later than 'source_item_type' \(VolumeMesh\)." + ) + with pytest.raises(ValueError, match=error_msg): + project_vm.run_case(params=params, start_from="SurfaceMesh")