From 46744500f5bbd9ea69af9325abe83a223dc74663 Mon Sep 17 00:00:00 2001 From: An Li Date: Fri, 2 Sep 2022 13:04:20 +0800 Subject: [PATCH 1/2] add volume mesh --- flow360/component/flow360_base_model.py | 22 ++ flow360/component/flow360_solver_params.py | 84 ++++++++ flow360/component/surface_mesh.py | 18 +- .../component/test_flow360_solver_params.py | 123 +++++++++++ flow360/component/volume_mesh.py | 194 ++++++++++++++++++ poetry.lock | 73 ++++++- pyproject.toml | 1 + tests/_test_surface_mesh.py | 4 +- tests/_test_volume_mesh.py | 87 ++++++++ 9 files changed, 589 insertions(+), 17 deletions(-) create mode 100644 flow360/component/flow360_base_model.py create mode 100644 flow360/component/flow360_solver_params.py create mode 100644 flow360/component/test_flow360_solver_params.py create mode 100644 flow360/component/volume_mesh.py create mode 100644 tests/_test_volume_mesh.py diff --git a/flow360/component/flow360_base_model.py b/flow360/component/flow360_base_model.py new file mode 100644 index 000000000..534b90ca1 --- /dev/null +++ b/flow360/component/flow360_base_model.py @@ -0,0 +1,22 @@ +""" +Flow360 base Model +""" +from datetime import datetime +from typing import List, Optional + +from pydantic import BaseModel, Extra, Field + + +class Flow360BaseModel(BaseModel, extra=Extra.allow): + """ + Flow360 base Model + """ + + name: str + user_id: Optional[str] = Field(alias="userId") + solver_version: Optional[str] = Field(alias="solverVersion") + tags: Optional[List[str]] + created_at: Optional[str] = Field(alias="createdAt") + updated_at: Optional[datetime] = Field(alias="updatedAt") + updated_by: Optional[str] = Field(alias="updatedBy") + user_upload_file_name: Optional[str] diff --git a/flow360/component/flow360_solver_params.py b/flow360/component/flow360_solver_params.py new file mode 100644 index 000000000..6789be207 --- /dev/null +++ b/flow360/component/flow360_solver_params.py @@ -0,0 +1,84 @@ +""" +Flow360 solver parameters +""" +from typing import Any, Dict, List, Optional, Union + +from pydantic import BaseModel, Extra, Field + + +class MeshBoundary(BaseModel): + """ + Mesh boundary + """ + + no_slip_walls: Optional[Union[List[str], List[int]]] = Field(alias="noSlipWalls") + + +class Flow360MeshParams(BaseModel): + """ + Flow360 mesh parameters + """ + + boundaries: MeshBoundary + + +class Boundary(BaseModel): + """ + Basic Boundary class + """ + + type: str + + +class NoSlipWall(Boundary): + """ + No slip wall boundary + """ + + type = "NoSlipWall" + velocity: Union[float, str] = Field(alias="Velocity") + + +class SlipWall(Boundary): + """ + Slip wall boundary + """ + + type = "SlipWall" + + +BoundaryType = Union[NoSlipWall, SlipWall] + + +class ActuatorDisk(BaseModel): + """ + Actuator disk component + """ + + center: Any + axis_thrust: Any = Field(alias="axisThrust") + thickness: Any + force_per_area: Any = Field(alias="forcePerArea") + + +class Flow360Params(BaseModel, extra=Extra.allow): + """ + Flow360 solver parameters + """ + + boundaries: Dict[str, BoundaryType] + actuator_disks: Optional[List[ActuatorDisk]] = Field(alias="actuatorDisks") + geometry: Any + run_control: Any = Field(alias="runControl") + freestream: Any = Field(alias="freestream") + volume_output: Any = Field(alias="volumeOutput") + surface_output: Any = Field(alias="surfaceOutput") + slice_output: Any = Field(alias="sliceOutput") + navier_stokes_solver: Any = Field(alias="navierStokesSolver") + turbulence_model_solver: Any = Field(alias="turbulenceModelSolver") + transition_model_solver: Any = Field(alias="transitionModelSolver") + initial_condition: Any = Field(alias="initialCondition") + time_stepping: Any = Field(alias="timeStepping") + sliding_interfaces: Any = Field(alias="slidingInterfaces") + BET_disks: Any = Field(alias="BETDisks") + porous_media: Any = Field(alias="porousMedia") diff --git a/flow360/component/surface_mesh.py b/flow360/component/surface_mesh.py index c560f642a..ce5720463 100644 --- a/flow360/component/surface_mesh.py +++ b/flow360/component/surface_mesh.py @@ -3,31 +3,23 @@ """ import json import os -from datetime import datetime -from typing import List, Optional +from typing import Optional -from pydantic import BaseModel, Extra, Field +from pydantic import Extra, Field from flow360.cloud.http_util import http from flow360.cloud.s3_utils import S3TransferType +from flow360.component.flow360_base_model import Flow360BaseModel -class SurfaceMesh(BaseModel, extra=Extra.allow): +class SurfaceMesh(Flow360BaseModel, extra=Extra.allow): """ Surface mesh component """ surface_mesh_id: Optional[str] = Field(alias="id") - name: str status: Optional[str] - user_id: Optional[str] = Field(alias="userId") - solver_version: Optional[str] = Field(alias="solverVersion") config: Optional[str] - tags: Optional[List[str]] - created_at: Optional[str] = Field(alias="createdAt") - updated_at: Optional[datetime] = Field(alias="updatedAt") - updated_by: Optional[str] = Field(alias="updatedBy") - user_upload_file_name: Optional[str] def download(self, file_name: str, to_file=".", keep_folder: bool = True): """ @@ -76,7 +68,7 @@ def from_cloud(cls, surface_mesh_id: str): return None @classmethod - def from_surface_mesh( + def from_file( cls, surface_mesh_name: str, file_name: str, solver_version: str = None, tags: [str] = None ): """ diff --git a/flow360/component/test_flow360_solver_params.py b/flow360/component/test_flow360_solver_params.py new file mode 100644 index 000000000..3d6389766 --- /dev/null +++ b/flow360/component/test_flow360_solver_params.py @@ -0,0 +1,123 @@ +from flow360.component.flow360_solver_params import ( + Flow360MeshParams, + Flow360Params, + MeshBoundary, +) + + +def test_boundary(): + assert MeshBoundary.parse_raw( + """ + { + "noSlipWalls": [ + "fluid/fuselage", + "fluid/leftWing", + "fluid/rightWing" + ] + } + """ + ) + assert MeshBoundary.parse_raw( + """ + { + "noSlipWalls": [ + 1, + 2, + 3 + ] + } + """ + ) + + +def test_flow360param(): + assert Flow360MeshParams.parse_raw( + """ + { + "boundaries": { + "noSlipWalls": [ + "fluid/fuselage", + "fluid/leftWing", + "fluid/rightWing" + ] + } +} + """ + ) + + assert Flow360MeshParams.parse_raw( + """ + { + "boundaries": { + "noSlipWalls": [ + 1, + 2, + 3 + ] + } + } + """ + ) + + +def test_flow360param(): + mesh = Flow360Params.parse_raw( + """ + { + "boundaries": { + "fluid/fuselage": { + "type": "NoSlipWall" + }, + "fluid/leftWing": { + "type": "NoSlipWall" + }, + "fluid/rightWing": { + "type": "NoSlipWall" + }, + "fluid/farfield": { + "type": "Freestream" + } + }, + "actuatorDisks": [ + { + "center": [ + 3.6, + -5.08354845, + 0 + ], + "axisThrust": [ + -0.96836405, + -0.06052275, + 0.24209101 + ], + "thickness": 0.42, + "forcePerArea": { + "radius": [], + "thrust": [], + "circumferential": [] + } + }, + { + "center": [ + 3.6, + 5.08354845, + 0 + ], + "axisThrust": [ + -0.96836405, + 0.06052275, + 0.24209101 + ], + "thickness": 0.42, + "forcePerArea": { + "radius": [], + "thrust": [], + "circumferential": [] + } + } + ] +} + """ + ) + + assert mesh diff --git a/flow360/component/volume_mesh.py b/flow360/component/volume_mesh.py new file mode 100644 index 000000000..9a13ad65a --- /dev/null +++ b/flow360/component/volume_mesh.py @@ -0,0 +1,194 @@ +""" +Surface mesh component +""" +import json +import os.path +from enum import Enum +from typing import Optional, Union + +from pydantic import Extra, Field + +from flow360.cloud.http_util import http +from flow360.cloud.s3_utils import S3TransferType +from flow360.component.flow360_base_model import Flow360BaseModel +from flow360.component.flow360_solver_params import Flow360MeshParams, Flow360Params + + +class VolumeMeshLog(Enum): + """ + Volume mesh log + """ + + USER_LOG = "user.log" + PY_LOG = "validateFlow360Mesh.py.log" + + +class VolumeMeshDownloadable(Enum): + """ + Volume mesh downloadable files + """ + + CONFIG_JSON = "config.json" + + +class UGRIDEndianness(Enum): + """ + UGRID endianness + """ + + LITTLE = "little" + BIG = "big" + + +class VolumeMeshFileFormat(Enum): + """ + Volume mesh file format + """ + + UGRID = "aflr3" + CGNS = "cgns" + + +class VolumeMesh(Flow360BaseModel, extra=Extra.allow): + """ + Surface mesh component + """ + + volume_mesh_id: Optional[str] = Field(alias="id") + name: str = Field(alias="meshName") + status: Optional[str] = Field(alias="meshStatus") + surface_mesh_id: Optional[str] = Field(alias="surfaceMeshId") + mesh_params: Optional[str] = Field(alias="meshParams") + + def download( + self, file_name: Union[str, VolumeMeshDownloadable], to_file=".", keep_folder: bool = True + ): + """ + Download file from surface mesh + :param file_name: + :param to_file: + :param keep_folder: + :return: + """ + assert self.volume_mesh_id + if isinstance(file_name, VolumeMeshDownloadable): + file_name = file_name.value + S3TransferType.VOLUME_MESH.download_file( + self.volume_mesh_id, file_name, to_file, keep_folder + ) + + def download_log(self, log: VolumeMeshLog, to_file=".", keep_folder: bool = True): + """ + Download log + :param log: + :param to_file: file name on local disk, could be either folder or file name. + :param keep_folder: If true, the downloaded file will be put in the same folder as the file on cloud. Only work + when file_name is a folder name. + :return: + """ + + self.download(f"logs/{log.value}", to_file, keep_folder) + + def submit(self): + """ + Submit surface mesh + :return: + """ + assert self.volume_mesh_id + http.post( + f"volumemeshes/{self.volume_mesh_id}/completeUpload?fileName={self.user_upload_file_name}" + ) + + @classmethod + def from_cloud(cls, surface_mesh_id: str): + """ + Get surface mesh info from cloud + :param surface_mesh_id: + :return: + """ + resp = http.get(f"volumemeshes/{surface_mesh_id}") + if resp: + return cls(**resp) + return None + + # pylint: disable=too-many-arguments + @classmethod + def from_surface_mesh( + cls, + volume_mesh_name: str, + surface_mesh_id: str, + config_file: str, + tags: [str] = None, + solver_version=None, + ): + """ + Create volume mesh from surface mesh + :param volume_mesh_name: + :param surface_mesh_id: + :param config_file: + :param tags: + :param solver_version: + :return: + """ + assert volume_mesh_name + assert os.path.exists(config_file) + assert surface_mesh_id + with open(config_file, "r", encoding="utf-8") as config_f: + json_content = json.load(config_f) + body = { + "name": volume_mesh_name, + "tags": tags, + "surfaceMeshId": surface_mesh_id, + "config": json.dumps(json_content), + "format": "cgns", + } + + if solver_version: + body["solverVersion"] = solver_version + + resp = http.post("volumemeshes", body) + if resp: + return cls(**resp) + return None + + # pylint: disable=too-many-arguments + @classmethod + def from_ugrid_file( + cls, + volume_mesh_name: str, + file_name: str, + params: Union[Flow360Params, Flow360MeshParams], + endianness: UGRIDEndianness = UGRIDEndianness.BIG, + tags: [str] = None, + solver_version=None, + ): + """ + Create volume mesh from ugrid file + :param volume_mesh_name: + :param file_name: + :param params: + :param endianness: + :param tags: + :param solver_version: + :return: + """ + assert volume_mesh_name + assert os.path.exists(file_name) + assert params + assert endianness + + body = { + "meshName": volume_mesh_name, + "meshTags": tags, + "meshFormat": "aflr3", + "meshEndianness": endianness.value, + "meshParams": params.json(), + } + + if solver_version: + body["solverVersion"] = solver_version + + resp = http.post("volumemeshes", body) + if resp: + return cls(**resp) + return None diff --git a/poetry.lock b/poetry.lock index e2c387c51..244c4a302 100644 --- a/poetry.lock +++ b/poetry.lock @@ -241,6 +241,17 @@ category = "dev" optional = false python-versions = ">=3.6" +[[package]] +name = "h5py" +version = "3.7.0" +description = "Read and write HDF5 files from Python" +category = "main" +optional = false +python-versions = ">=3.7" + +[package.dependencies] +numpy = ">=1.14.5" + [[package]] name = "httpcore" version = "0.15.0" @@ -358,6 +369,14 @@ category = "dev" optional = false python-versions = "*" +[[package]] +name = "numpy" +version = "1.21.1" +description = "NumPy is the fundamental package for array computing with Python." +category = "main" +optional = false +python-versions = ">=3.7" + [[package]] name = "packaging" version = "21.3" @@ -674,7 +693,7 @@ testing = ["func-timeout", "jaraco.itertools", "pytest (>=6)", "pytest-black (>= [metadata] lock-version = "1.1" python-versions = "^3.7.2" -content-hash = "2da1154eefcba630aab3e87549a0179d3ebc55e776078fe46f5c304ba033a28f" +content-hash = "ba3f6cdef7b4cee2d74b81afd9112fa7b4b907a42c3f5e5424dd719949c6847a" [metadata.files] anyio = [ @@ -773,6 +792,28 @@ h11 = [ {file = "h11-0.12.0-py3-none-any.whl", hash = "sha256:36a3cb8c0a032f56e2da7084577878a035d3b61d104230d4bd49c0c6b555a9c6"}, {file = "h11-0.12.0.tar.gz", hash = "sha256:47222cb6067e4a307d535814917cd98fd0a57b6788ce715755fa2b6c28b56042"}, ] +h5py = [ + {file = "h5py-3.7.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:d77af42cb751ad6cc44f11bae73075a07429a5cf2094dfde2b1e716e059b3911"}, + {file = "h5py-3.7.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:63beb8b7b47d0896c50de6efb9a1eaa81dbe211f3767e7dd7db159cea51ba37a"}, + {file = "h5py-3.7.0-cp310-cp310-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:04e2e1e2fc51b8873e972a08d2f89625ef999b1f2d276199011af57bb9fc7851"}, + {file = "h5py-3.7.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f73307c876af49aa869ec5df1818e9bb0bdcfcf8a5ba773cc45a4fba5a286a5c"}, + {file = "h5py-3.7.0-cp310-cp310-win_amd64.whl", hash = "sha256:f514b24cacdd983e61f8d371edac8c1b780c279d0acb8485639e97339c866073"}, + {file = "h5py-3.7.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:43fed4d13743cf02798a9a03a360a88e589d81285e72b83f47d37bb64ed44881"}, + {file = "h5py-3.7.0-cp37-cp37m-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:c038399ce09a58ff8d89ec3e62f00aa7cb82d14f34e24735b920e2a811a3a426"}, + {file = "h5py-3.7.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:03d64fb86bb86b978928bad923b64419a23e836499ec6363e305ad28afd9d287"}, + {file = "h5py-3.7.0-cp37-cp37m-win_amd64.whl", hash = "sha256:e5b7820b75f9519499d76cc708e27242ccfdd9dfb511d6deb98701961d0445aa"}, + {file = "h5py-3.7.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:a9351d729ea754db36d175098361b920573fdad334125f86ac1dd3a083355e20"}, + {file = "h5py-3.7.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:6776d896fb90c5938de8acb925e057e2f9f28755f67ec3edcbc8344832616c38"}, + {file = "h5py-3.7.0-cp38-cp38-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:0a047fddbe6951bce40e9cde63373c838a978c5e05a011a682db9ba6334b8e85"}, + {file = "h5py-3.7.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0798a9c0ff45f17d0192e4d7114d734cac9f8b2b2c76dd1d923c4d0923f27bb6"}, + {file = "h5py-3.7.0-cp38-cp38-win_amd64.whl", hash = "sha256:0d8de8cb619fc597da7cf8cdcbf3b7ff8c5f6db836568afc7dc16d21f59b2b49"}, + {file = "h5py-3.7.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:f084bbe816907dfe59006756f8f2d16d352faff2d107f4ffeb1d8de126fc5dc7"}, + {file = "h5py-3.7.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:1fcb11a2dc8eb7ddcae08afd8fae02ba10467753a857fa07a404d700a93f3d53"}, + {file = "h5py-3.7.0-cp39-cp39-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:ed43e2cc4f511756fd664fb45d6b66c3cbed4e3bd0f70e29c37809b2ae013c44"}, + {file = "h5py-3.7.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9e7535df5ee3dc3e5d1f408fdfc0b33b46bc9b34db82743c82cd674d8239b9ad"}, + {file = "h5py-3.7.0-cp39-cp39-win_amd64.whl", hash = "sha256:9e2ad2aa000f5b1e73b5dfe22f358ca46bf1a2b6ca394d9659874d7fc251731a"}, + {file = "h5py-3.7.0.tar.gz", hash = "sha256:3fcf37884383c5da64846ab510190720027dca0768def34dd8dcb659dbe5cbf3"}, +] httpcore = [ {file = "httpcore-0.15.0-py3-none-any.whl", hash = "sha256:1105b8b73c025f23ff7c36468e4432226cbb959176eab66864b8e31c4ee27fa6"}, {file = "httpcore-0.15.0.tar.gz", hash = "sha256:18b68ab86a3ccf3e7dc0f43598eaddcf472b602aba29f9aa6ab85fe2ada3980b"}, @@ -848,6 +889,36 @@ mypy-extensions = [ {file = "mypy_extensions-0.4.3-py2.py3-none-any.whl", hash = "sha256:090fedd75945a69ae91ce1303b5824f428daf5a028d2f6ab8a299250a846f15d"}, {file = "mypy_extensions-0.4.3.tar.gz", hash = "sha256:2d82818f5bb3e369420cb3c4060a7970edba416647068eb4c5343488a6c604a8"}, ] +numpy = [ + {file = "numpy-1.21.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:38e8648f9449a549a7dfe8d8755a5979b45b3538520d1e735637ef28e8c2dc50"}, + {file = "numpy-1.21.1-cp37-cp37m-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:fd7d7409fa643a91d0a05c7554dd68aa9c9bb16e186f6ccfe40d6e003156e33a"}, + {file = "numpy-1.21.1-cp37-cp37m-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:a75b4498b1e93d8b700282dc8e655b8bd559c0904b3910b144646dbbbc03e062"}, + {file = "numpy-1.21.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1412aa0aec3e00bc23fbb8664d76552b4efde98fb71f60737c83efbac24112f1"}, + {file = "numpy-1.21.1-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:e46ceaff65609b5399163de5893d8f2a82d3c77d5e56d976c8b5fb01faa6b671"}, + {file = "numpy-1.21.1-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:c6a2324085dd52f96498419ba95b5777e40b6bcbc20088fddb9e8cbb58885e8e"}, + {file = "numpy-1.21.1-cp37-cp37m-win32.whl", hash = "sha256:73101b2a1fef16602696d133db402a7e7586654682244344b8329cdcbbb82172"}, + {file = "numpy-1.21.1-cp37-cp37m-win_amd64.whl", hash = "sha256:7a708a79c9a9d26904d1cca8d383bf869edf6f8e7650d85dbc77b041e8c5a0f8"}, + {file = "numpy-1.21.1-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:95b995d0c413f5d0428b3f880e8fe1660ff9396dcd1f9eedbc311f37b5652e16"}, + {file = "numpy-1.21.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:635e6bd31c9fb3d475c8f44a089569070d10a9ef18ed13738b03049280281267"}, + {file = "numpy-1.21.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:4a3d5fb89bfe21be2ef47c0614b9c9c707b7362386c9a3ff1feae63e0267ccb6"}, + {file = "numpy-1.21.1-cp38-cp38-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:8a326af80e86d0e9ce92bcc1e65c8ff88297de4fa14ee936cb2293d414c9ec63"}, + {file = "numpy-1.21.1-cp38-cp38-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:791492091744b0fe390a6ce85cc1bf5149968ac7d5f0477288f78c89b385d9af"}, + {file = "numpy-1.21.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0318c465786c1f63ac05d7c4dbcecd4d2d7e13f0959b01b534ea1e92202235c5"}, + {file = "numpy-1.21.1-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:9a513bd9c1551894ee3d31369f9b07460ef223694098cf27d399513415855b68"}, + {file = "numpy-1.21.1-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:91c6f5fc58df1e0a3cc0c3a717bb3308ff850abdaa6d2d802573ee2b11f674a8"}, + {file = "numpy-1.21.1-cp38-cp38-win32.whl", hash = "sha256:978010b68e17150db8765355d1ccdd450f9fc916824e8c4e35ee620590e234cd"}, + {file = "numpy-1.21.1-cp38-cp38-win_amd64.whl", hash = "sha256:9749a40a5b22333467f02fe11edc98f022133ee1bfa8ab99bda5e5437b831214"}, + {file = "numpy-1.21.1-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:d7a4aeac3b94af92a9373d6e77b37691b86411f9745190d2c351f410ab3a791f"}, + {file = "numpy-1.21.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:d9e7912a56108aba9b31df688a4c4f5cb0d9d3787386b87d504762b6754fbb1b"}, + {file = "numpy-1.21.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:25b40b98ebdd272bc3020935427a4530b7d60dfbe1ab9381a39147834e985eac"}, + {file = "numpy-1.21.1-cp39-cp39-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:8a92c5aea763d14ba9d6475803fc7904bda7decc2a0a68153f587ad82941fec1"}, + {file = "numpy-1.21.1-cp39-cp39-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:05a0f648eb28bae4bcb204e6fd14603de2908de982e761a2fc78efe0f19e96e1"}, + {file = "numpy-1.21.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f01f28075a92eede918b965e86e8f0ba7b7797a95aa8d35e1cc8821f5fc3ad6a"}, + {file = "numpy-1.21.1-cp39-cp39-win32.whl", hash = "sha256:88c0b89ad1cc24a5efbb99ff9ab5db0f9a86e9cc50240177a571fbe9c2860ac2"}, + {file = "numpy-1.21.1-cp39-cp39-win_amd64.whl", hash = "sha256:01721eefe70544d548425a07c80be8377096a54118070b8a62476866d5208e33"}, + {file = "numpy-1.21.1-pp37-pypy37_pp73-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:2d4d1de6e6fb3d28781c73fbde702ac97f03d79e4ffd6598b880b2d95d62ead4"}, + {file = "numpy-1.21.1.zip", hash = "sha256:dff4af63638afcc57a3dfb9e4b26d434a7a602d225b42d746ea7fe2edf1342fd"}, +] packaging = [ {file = "packaging-21.3-py3-none-any.whl", hash = "sha256:ef103e05f519cdc783ae24ea4e2e0f508a9c99b2d4969652eed6a2e1ea5bd522"}, {file = "packaging-21.3.tar.gz", hash = "sha256:dd47c42927d89ab911e606518907cc2d3a1f38bbd026385970643f9c5b8ecfeb"}, diff --git a/pyproject.toml b/pyproject.toml index 87bb2bc71..733f8efbe 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -12,6 +12,7 @@ click = "^8.1.3" toml = "^0.10.2" requests = "^2.28.1" boto3 = "^1.24.63" +h5py = "^3.7.0" [tool.poetry.dev-dependencies] pytest = "^7.1.2" diff --git a/tests/_test_surface_mesh.py b/tests/_test_surface_mesh.py index 1ce2d92a7..bfa518931 100644 --- a/tests/_test_surface_mesh.py +++ b/tests/_test_surface_mesh.py @@ -29,9 +29,7 @@ def test_download(): def test_create_update(): Env.dev.active() - mesh = SurfaceMesh.from_surface_mesh( - "test_name", "3f358de7-432e-4a1f-af26-ad53a3b84088/geometry.csm" - ) + mesh = SurfaceMesh.from_file("test_name", "3f358de7-432e-4a1f-af26-ad53a3b84088/geometry.csm") assert mesh mesh.submit() diff --git a/tests/_test_volume_mesh.py b/tests/_test_volume_mesh.py new file mode 100644 index 000000000..6140e7f47 --- /dev/null +++ b/tests/_test_volume_mesh.py @@ -0,0 +1,87 @@ +import os + +from flow360 import Env +from flow360.component.flow360_solver_params import Flow360MeshParams +from flow360.component.surface_mesh import SurfaceMesh +from flow360.component.volume_mesh import ( + VolumeMesh, + VolumeMeshDownloadable, + VolumeMeshLog, +) + + +def test_from_cloud(): + Env.dev.active() + mesh = VolumeMesh.from_cloud("768aaf6b-37d9-471d-8246-9f0da9060bb6") + assert mesh + # mesh.download_log(to_file="./test_surface_mesh.log") + # assert os.path.exists("./test_surface_mesh.log") + # mesh.download_log() + # assert os.path.exists( + # "./3f358de7-432e-4a1f-af26-ad53a3b84088/logs/flow360_surface_mesh.user.log" + # ) + # + # mesh.download_log(to_file="..") + # assert os.path.exists( + # "../3f358de7-432e-4a1f-af26-ad53a3b84088/logs/flow360_surface_mesh.user.log" + # ) + + +def test_download_log(): + Env.dev.active() + mesh = VolumeMesh.from_cloud("768aaf6b-37d9-471d-8246-9f0da9060bb6") + mesh.download_log(VolumeMeshLog.USER_LOG, to_file="./test_volume_mesh.log") + assert os.path.exists("./test_volume_mesh.log") + + +def test_download(): + Env.dev.active() + mesh = VolumeMesh.from_cloud("768aaf6b-37d9-471d-8246-9f0da9060bb6") + mesh.download(file_name="Flow360Mesh.json") + assert os.path.exists("768aaf6b-37d9-471d-8246-9f0da9060bb6/Flow360Mesh.json") + mesh.download(file_name=VolumeMeshDownloadable.CONFIG_JSON) + + +def test_create(): + Env.dev.active() + mesh = SurfaceMesh.from_cloud("3f358de7-432e-4a1f-af26-ad53a3b84088") + mesh = VolumeMesh.from_surface_mesh( + "Volume Mesh", mesh.surface_mesh_id, "768aaf6b-37d9-471d-8246-9f0da9060bb6/Flow360Mesh.json" + ) + assert mesh + mesh.submit() + + +def test_from_geometry(): + Env.dev.active() + mesh = SurfaceMesh.from_cloud("3f358de7-432e-4a1f-af26-ad53a3b84088") + mesh.download("config.json") + + mesh = SurfaceMesh.from_geometry( + "test_name", + "3f358de7-432e-4a1f-af26-ad53a3b84088/geometry.csm", + "3f358de7-432e-4a1f-af26-ad53a3b84088/config.json", + ) + mesh.submit() + + +def test_ugrid_file(): + Env.dev.active() + + params = Flow360MeshParams.parse_raw( + """ + { + "boundaries": { + "noSlipWalls": [ + "fluid/fuselage", + "fluid/leftWing", + "fluid/rightWing" + ] + } + } + """ + ) + mesh = VolumeMesh.from_ugrid_file( + "test_ugrid", "3f358de7-432e-4a1f-af26-ad53a3b84088/geometry.csm", params + ) + assert mesh From 5b2e723bdf3ffe8f3f0c568514120641e65d66a4 Mon Sep 17 00:00:00 2001 From: An Li Date: Fri, 2 Sep 2022 15:00:22 +0800 Subject: [PATCH 2/2] remove h5py --- flow360/cloud/http_util.py | 3 ++- flow360/component/flow360_solver_params.py | 17 +---------------- pyproject.toml | 1 - 3 files changed, 3 insertions(+), 18 deletions(-) diff --git a/flow360/cloud/http_util.py b/flow360/cloud/http_util.py index c9a85dbc4..bdc381394 100644 --- a/flow360/cloud/http_util.py +++ b/flow360/cloud/http_util.py @@ -6,7 +6,7 @@ import requests -from flow360 import Env +from flow360 import Env, __version__ from flow360.cloud.security import api_key @@ -20,6 +20,7 @@ def api_key_auth(request): if not key: raise ValueError("API key not found, please set it by commandline: flow360 configure.") request.headers["simcloud-api-key"] = key + request.headers["flow360-python-version"] = __version__ return request diff --git a/flow360/component/flow360_solver_params.py b/flow360/component/flow360_solver_params.py index 6789be207..5030918c6 100644 --- a/flow360/component/flow360_solver_params.py +++ b/flow360/component/flow360_solver_params.py @@ -66,19 +66,4 @@ class Flow360Params(BaseModel, extra=Extra.allow): Flow360 solver parameters """ - boundaries: Dict[str, BoundaryType] - actuator_disks: Optional[List[ActuatorDisk]] = Field(alias="actuatorDisks") - geometry: Any - run_control: Any = Field(alias="runControl") - freestream: Any = Field(alias="freestream") - volume_output: Any = Field(alias="volumeOutput") - surface_output: Any = Field(alias="surfaceOutput") - slice_output: Any = Field(alias="sliceOutput") - navier_stokes_solver: Any = Field(alias="navierStokesSolver") - turbulence_model_solver: Any = Field(alias="turbulenceModelSolver") - transition_model_solver: Any = Field(alias="transitionModelSolver") - initial_condition: Any = Field(alias="initialCondition") - time_stepping: Any = Field(alias="timeStepping") - sliding_interfaces: Any = Field(alias="slidingInterfaces") - BET_disks: Any = Field(alias="BETDisks") - porous_media: Any = Field(alias="porousMedia") + boundaries: Optional[Dict[str, BoundaryType]] diff --git a/pyproject.toml b/pyproject.toml index 733f8efbe..87bb2bc71 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -12,7 +12,6 @@ click = "^8.1.3" toml = "^0.10.2" requests = "^2.28.1" boto3 = "^1.24.63" -h5py = "^3.7.0" [tool.poetry.dev-dependencies] pytest = "^7.1.2"