diff --git a/examples/data/bem.nc b/examples/data/bem.nc index bca7066d..45be488d 100644 Binary files a/examples/data/bem.nc and b/examples/data/bem.nc differ diff --git a/examples/tutorial_1_WaveBot.ipynb b/examples/tutorial_1_WaveBot.ipynb index 00d2badb..48731579 100644 --- a/examples/tutorial_1_WaveBot.ipynb +++ b/examples/tutorial_1_WaveBot.ipynb @@ -32,6 +32,7 @@ "source": [ "import autograd.numpy as np\n", "import capytaine as cpy\n", + "from capytaine.io.meshio import load_from_meshio\n", "import matplotlib.pyplot as plt\n", "from scipy.optimize import brute\n", "\n", @@ -135,7 +136,11 @@ "#### WEC geometry mesh\n", "Now we will create a surface mesh for the WEC hull and store it using the `FloatingBody` object from Capytaine.\n", "The WaveBot mesh is pre-defined in the `wecopttool.geom` module, so we will call it directly from there.\n", - "Note that the Capytaine `from_meshio` method can also import from other file types (STL, VTK, MSH, etc.), click [here](https://pypi.org/project/meshio/) for the full list of compatible mesh file types." + "Note that the Capytaine `from_meshio` method can also import from other file types (STL, VTK, MSH, etc.), click [here](https://pypi.org/project/meshio/) for the full list of compatible mesh file types.\n", + "\n", + "We also apply an internal lid which helps eliminate irregular frequency spikes. \n", + "The lid position was chosen by iterating through a series of mesh size factors and lid positions to move the frequency spikes above the range of interest. \n", + "See the `capytaine` documentation [here](https://capytaine.github.io/stable/index.html#) for more details. " ] }, { @@ -145,9 +150,14 @@ "outputs": [], "source": [ "wb = wot.geom.WaveBot() # use standard dimensions\n", - "mesh_size_factor = 0.5 # 1.0 for default, smaller to refine mesh\n", + "mesh_size_factor = 0.2 # 1.0 for default, smaller to refine mesh\n", "mesh = wb.mesh(mesh_size_factor)\n", - "fb = cpy.FloatingBody.from_meshio(mesh, name=\"WaveBot\")" + "\n", + "# create mesh object for WaveBot and add internal lid\n", + "mesh_obj = load_from_meshio(mesh, 'WaveBot')\n", + "lid_mesh = mesh_obj.generate_lid(-2e-2)\n", + "\n", + "fb = cpy.FloatingBody(mesh=mesh_obj, lid_mesh=lid_mesh, name=\"WaveBot\")" ] }, { diff --git a/examples/tutorial_2_AquaHarmonics.ipynb b/examples/tutorial_2_AquaHarmonics.ipynb index 8d42ede4..d68d8356 100644 --- a/examples/tutorial_2_AquaHarmonics.ipynb +++ b/examples/tutorial_2_AquaHarmonics.ipynb @@ -23,6 +23,7 @@ "outputs": [], "source": [ "import capytaine as cpy\n", + "from capytaine.io.meshio import load_from_meshio\n", "import autograd.numpy as np\n", "import matplotlib.pyplot as plt\n", "from matplotlib import cm\n", @@ -68,6 +69,7 @@ "metadata": {}, "source": [ "Next we create a `FloatingBody` object from the mesh in Capytaine, which we will use to calculate the hydrodynamics.\n", + "We add a lid mesh to remove irregular frequency spikes, similar to [Tutorial 1](https://github.com/sandialabs/WecOptTool/blob/main/examples/tutorial_1_WaveBot.ipynb).\n", "We can visualize a 3D rendering of the mesh now as well." ] }, @@ -77,7 +79,10 @@ "metadata": {}, "outputs": [], "source": [ - "fb = cpy.FloatingBody.from_meshio(mesh, name=\"AquaHarmonics\")\n", + "mesh_obj = load_from_meshio(mesh, 'WaveBot')\n", + "lid_mesh = mesh_obj.generate_lid(-5e-2)\n", + "\n", + "fb = cpy.FloatingBody(mesh=mesh_obj, lid_mesh=lid_mesh, name=\"AquaHarmonics\")\n", "fb.add_translation_dof(name=\"Heave\")\n", "ndof = fb.nb_dofs\n", "fb.show_matplotlib()" @@ -125,7 +130,7 @@ "outputs": [], "source": [ "amplitude = 0.5\n", - "wavefreq = 0.24/2 \n", + "wavefreq = 0.24/2 \n", "phase = 30\n", "wavedir = 0\n", "\n", diff --git a/examples/tutorial_3_LUPA.ipynb b/examples/tutorial_3_LUPA.ipynb index 7aee3744..710a59c4 100644 --- a/examples/tutorial_3_LUPA.ipynb +++ b/examples/tutorial_3_LUPA.ipynb @@ -39,6 +39,7 @@ "\n", "import gmsh, pygmsh\n", "import capytaine as cpy\n", + "from capytaine.io.meshio import load_from_meshio\n", "import autograd.numpy as np\n", "import matplotlib.pyplot as plt\n", "import xarray as xr\n", @@ -103,9 +104,10 @@ "Here we create the mesh based on the dimensions provided by Oregon State University using `pygmsh`, available [here](https://pypi.org/project/pygmsh/).\n", "This is the same package used by `geom.py` (click [here](https://sandialabs.github.io/WecOptTool/api_docs/wecopttool.geom.html) for API documentation) containing the predefined WaveBot and AquaHarmonics meshes used in the previous tutorials.\n", "\n", - "The float has a hole where the spar passes through it, though OSU has found that this hole creates a large spike in the BEM results at about 4.5 rad/s.\n", - "There is not much energy in the waves at this frequency in the wave spectrum we will be using, so this spike should not significantly affect our results.\n", - "If you would like to remove this spike and create smoother BEM results, set `hole = False` in the cell below." + "The float has a hole where the spar passes through it. \n", + "In previous versions of this tutorial, the hole was larger than the spar and led to a large spike in the BEM results. \n", + "The spike has been resolved by making the hole smaller so that the float is flush with the spar.\n", + "Like the other tutorials, a lid is added to remove any irregular frequency spikes. " ] }, { @@ -121,20 +123,16 @@ "h1 = 0.5 \n", "h2 = 0.21\n", "freeboard = 0.3\n", - "r3 = 0.10/2 + 0.05 # hole radius\n", - "hole = True # set to False to remove spike in BEM results\n", + "r3 = 0.05 # hole radius\n", "with pygmsh.occ.Geometry() as geom:\n", " gmsh.option.setNumber('Mesh.MeshSizeFactor', mesh_size_factor)\n", " cyl = geom.add_cylinder([0, 0, 0], [0, 0, -h1], r1)\n", " cone = geom.add_cone([0, 0, -h1], [0, 0, -h2], r1, r2)\n", " geom.translate(cyl, [0, 0, freeboard])\n", " geom.translate(cone, [0, 0, freeboard]) \n", - " if hole:\n", - " tmp = geom.boolean_union([cyl, cone])\n", - " bar = geom.add_cylinder([0, 0, 10], [0,0,-20], r3)\n", - " geom.boolean_difference(tmp, bar)\n", - " else:\n", - " geom.boolean_union([cyl, cone])\n", + " tmp = geom.boolean_union([cyl, cone])\n", + " bar = geom.add_cylinder([0, 0, 10], [0,0,-20], r3)\n", + " geom.boolean_difference(tmp, bar)\n", " mesh_float = geom.generate_mesh()" ] }, @@ -152,8 +150,12 @@ "metadata": {}, "outputs": [], "source": [ + "# lid\n", + "mesh_obj = load_from_meshio(mesh_float, 'float')\n", + "lid_mesh = mesh_obj.generate_lid(z=-1e-2)\n", + "\n", "# floating body\n", - "float_fb = cpy.FloatingBody.from_meshio(mesh_float, name='float')\n", + "float_fb = cpy.FloatingBody(mesh=mesh_obj, lid_mesh=lid_mesh, name=\"float\")\n", "float_fb.add_translation_dof(name='Heave')" ] }, @@ -221,8 +223,12 @@ "metadata": {}, "outputs": [], "source": [ + "# lid\n", + "mesh_obj = load_from_meshio(mesh_spar, 'float')\n", + "lid_mesh = mesh_obj.generate_lid(z=-1e-2)\n", + "\n", "# floating body\n", - "spar_fb = cpy.FloatingBody.from_meshio(mesh_spar, name='spar')\n", + "spar_fb = cpy.FloatingBody(mesh=mesh_obj, lid_mesh=lid_mesh, name=\"spar\")\n", "spar_fb.add_translation_dof(name='Heave')" ] }, diff --git a/examples/tutorial_4_Pioneer.ipynb b/examples/tutorial_4_Pioneer.ipynb index 45cc13b2..ae739b7d 100644 --- a/examples/tutorial_4_Pioneer.ipynb +++ b/examples/tutorial_4_Pioneer.ipynb @@ -35,6 +35,7 @@ "outputs": [], "source": [ "import capytaine as cpy\n", + "from capytaine.io.meshio import load_from_meshio\n", "import autograd.numpy as np\n", "import matplotlib.pyplot as plt\n", "from scipy.linalg import block_diag\n", @@ -148,7 +149,7 @@ " h2=17.321 * in2m,\n", " scale_factor=1,\n", " freeboard=freeboard)\n", - "mesh = hull_geom.mesh(mesh_size_factor=0.5)\n", + "mesh = hull_geom.mesh(mesh_size_factor=0.3)\n", "_ = hull_geom.plot_cross_section()" ] }, @@ -253,7 +254,10 @@ "metadata": {}, "outputs": [], "source": [ - "pnr_fb = cpy.FloatingBody.from_meshio(mesh, name=\"Pioneer\")\n", + "mesh_obj = load_from_meshio(mesh, 'Pioneer')\n", + "lid_mesh = mesh_obj.generate_lid(-4e-2)\n", + "\n", + "pnr_fb = cpy.FloatingBody(mesh=mesh_obj, lid_mesh=lid_mesh, name=\"WaveBot\")\n", "pnr_fb.add_rotation_dof(name='Pitch')\n", "pnr_fb.center_of_mass = np.array([0., 0., buoy_props['CG']])\n", "pnr_fb.rotation_center = pnr_fb.center_of_mass\n",