{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Generate loft from a parameter config file" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Load configs" ] }, { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "LoftCaseConfig(reference_direction=[-1, 0, 0], cases={'default': LoftParams(loft_length=1200.0, mesh_element_size=25.0, wind_source_angles=[0.0, 45.0, 135.0, 90.0], upwind_elevation=780.0), 'longer_loft': LoftParams(loft_length=1500.0, mesh_element_size=25.0, wind_source_angles=[180.0, 270.0, 225.0], upwind_elevation=780.0)})" ] }, "execution_count": 1, "metadata": {}, "output_type": "execute_result" } ], "source": [ "from cfdmod.use_cases.loft.parameters import LoftCaseConfig\n", "import pathlib\n", "\n", "cfg_file = pathlib.Path(\"./fixtures/tests/loft/loft_params.yaml\")\n", "cfg = LoftCaseConfig.from_file(cfg_file)\n", "\n", "cfg" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Load surface mesh" ] }, { "cell_type": "code", "execution_count": 2, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "(array([[[ 622.19226 , 7.6139417, 774.35693 ],\n", " [ 620.78424 , 7.970398 , 773.9987 ],\n", " [ 614.316 , 4.6423063, 773.50385 ]],\n", " \n", " [[ 645.47797 , -15.484023 , 767.435 ],\n", " [ 643.78357 , -16.447126 , 766.5187 ],\n", " [ 645.73376 , -16.655039 , 766.02747 ]],\n", " \n", " [[ 642.06805 , -12.476355 , 767.9776 ],\n", " [ 632.3187 , -4.6019497, 770.26587 ],\n", " [ 642.0133 , -14.797253 , 767.05884 ]],\n", " \n", " ...,\n", " \n", " [[ 605.6187 , -651.87646 , 757.34576 ],\n", " [ 615.6246 , -675.4446 , 757.1043 ],\n", " [ 627.32086 , -659.3153 , 760.9082 ]],\n", " \n", " [[ 605.6187 , -651.87646 , 757.34576 ],\n", " [ 591.1564 , -671.6936 , 755.1523 ],\n", " [ 615.6246 , -675.4446 , 757.1043 ]],\n", " \n", " [[ 610.7315 , 9.4921 , 780.0834 ],\n", " [ 620.91907 , 9.256538 , 790.40234 ],\n", " [ 585.0646 , 9.5950575, 791.08875 ]]], dtype=float32),\n", " array([[-0.18731488, 0.22175997, 0.95694077],\n", " [ 0.08185904, -0.7587941 , 0.6461661 ],\n", " [-0.07739674, -0.36539087, 0.92763096],\n", " ...,\n", " [-0.19173947, -0.09141431, 0.9771793 ],\n", " [-0.08658855, -0.04695639, 0.995137 ],\n", " [-0.00969394, -0.9998652 , -0.01325442]], dtype=float32))" ] }, "execution_count": 2, "metadata": {}, "output_type": "execute_result" } ], "source": [ "from cfdmod.api.geometry.STL import read_stl\n", "\n", "mesh_path = pathlib.Path(\"./fixtures/tests/loft/terrain.stl\")\n", "\n", "triangles, normals = read_stl(mesh_path)\n", "\n", "triangles, normals" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Generate loft" ] }, { "cell_type": "code", "execution_count": 4, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\u001b[37m[2024-11-14 13:06:27,872] [INFO] - cfdmod - Generating loft for default/0.0... (1613004650.py:13)\u001b[39m\n", "\u001b[37m[2024-11-14 13:06:34,808] [INFO] - cfdmod - Generating loft for longer_loft/270.0... (1613004650.py:13)\u001b[39m\n", "\u001b[37m[2024-11-14 13:06:42,053] [INFO] - cfdmod - Generating loft for inherit_loft/0.0... (1613004650.py:13)\u001b[39m\n", "\u001b[37m[2024-11-14 13:06:50,913] [INFO] - cfdmod - Generating loft for inherit_element_size/270.0... (1613004650.py:13)\u001b[39m\n" ] } ], "source": [ "from cfdmod.use_cases.loft.functions import (\n", " generate_loft_surface,\n", " apply_remeshing,\n", " rotate_vector_around_z,\n", ")\n", "import numpy as np\n", "from cfdmod.api.geometry.STL import export_stl\n", "from cfdmod.logger import logger\n", "\n", "output_path = pathlib.Path(\"./output/loft\")\n", "\n", "for case_lbl, loft_params in cfg.cases.items():\n", " logger.info(f\"Generating loft for {case_lbl}/{loft_params.wind_source_angle}...\")\n", " wind_source_direction = rotate_vector_around_z(\n", " np.array(cfg.reference_direction, dtype=np.float32), loft_params.wind_source_angle\n", " )\n", " loft_directions = {\n", " \"upwind\": -np.array(wind_source_direction),\n", " \"downwind\": np.array(wind_source_direction),\n", " }\n", "\n", " for side, direction in loft_directions.items():\n", " loft_tri, loft_normals = generate_loft_surface(\n", " triangle_vertices=triangles,\n", " projection_diretion=direction,\n", " loft_length=loft_params.loft_length,\n", " loft_z_pos=loft_params.upwind_elevation,\n", " )\n", "\n", " export_stl(\n", " output_path / f\"{case_lbl}\" / f\"{loft_params.wind_source_angle}\" / f\"{side}_loft.stl\",\n", " loft_tri,\n", " loft_normals,\n", " )\n", " apply_remeshing(\n", " element_size=loft_params.mesh_element_size,\n", " mesh_path=output_path\n", " / f\"{case_lbl}\"\n", " / f\"{loft_params.wind_source_angle}\"\n", " / f\"{side}_loft.stl\",\n", " output_path=output_path\n", " / f\"{case_lbl}\"\n", " / f\"{loft_params.wind_source_angle}\"\n", " / f\"{side}_loft_remeshed.stl\",\n", " )\n", " export_stl(\n", " output_path / f\"{case_lbl}\" / f\"{loft_params.wind_source_angle}\" / \"terrain.stl\",\n", " triangles,\n", " normals,\n", " )\n", " apply_remeshing(\n", " element_size=loft_params.mesh_element_size,\n", " mesh_path=output_path / f\"{case_lbl}\" / f\"{loft_params.wind_source_angle}\" / \"terrain.stl\",\n", " output_path=output_path\n", " / f\"{case_lbl}\"\n", " / f\"{loft_params.wind_source_angle}\"\n", " / \"terrain_remeshed.stl\",\n", " )" ] } ], "metadata": { "kernelspec": { "display_name": "cfdmod-XMkUSlb0-py3.10", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.10.11" }, "orig_nbformat": 4 }, "nbformat": 4, "nbformat_minor": 2 }