Source code for capytaine.post_pro.free_surfaces
"""This module implements objects describing a mesh on which the free surface elevation will be computed."""
# Copyright (C) 2017-2019 Matthieu Ancellin
# See LICENSE file at <https://github.com/mancellin/capytaine>
import logging
from itertools import product
import numpy as np
from capytaine.meshes.meshes import Mesh
LOG = logging.getLogger(__name__)
[docs]
class FreeSurface():
"""A cartesian mesh on which the free surface elevation will be computed.
Has a :code:`mesh` attribute to behave kind of like FloatingBody when
building of the influence matrix.
Parameters
----------
x_range: Tuple[float, float], optional
extreme values of the mesh in the x direction
nx: int, optional
number of cells in the x direction
y_range: Tuple[float, float], optional
extreme values of the mesh in the y direction
ny: int, optional
number of cells in the y direction
name: string, optional
a name for the free surface object
.. todo:: Generalize to non-cartesian meshes.
In particular, it could be of interest to build meshes having the
same symmetry as a given floating body to speed up the
construction of the influence matrix.
.. seealso::
:meth:`~capytaine.bem.nemoh.Nemoh.get_free_surface_elevation`
The main function requiring a FreeSurface object.
"""
def __init__(self, x_range=(-50.0, 50.0), nx=10, y_range=(-50.0, 50.0), ny=10, name=None):
self.x_range = x_range
self.nx = nx
self.y_range = y_range
self.ny = ny
if name is None:
self.name = f"free_surface_{next(Mesh._ids)}"
else:
self.name = name
self.mesh = self._generate_mesh()
def _generate_mesh(self):
"""Generate a 2D cartesian mesh."""
nodes = np.zeros(((self.nx+1)*(self.ny+1), 3), dtype=float)
panels = np.zeros((self.nx*self.ny, 4), dtype=int)
X = np.linspace(*self.x_range, self.nx+1)
Y = np.linspace(*self.y_range, self.ny+1)
for i, (x, y, z) in enumerate(product(X, Y, [0.0])):
nodes[i, :] = x, y, z
for k, (i, j) in enumerate(product(range(0, self.nx), range(0, self.ny))):
panels[k, :] = (j+i*(self.ny+1),
(j+1)+i*(self.ny+1),
(j+1)+(i+1)*(self.ny+1),
j+(i+1)*(self.ny+1))
return Mesh(nodes, panels, name=f"{self.name}_mesh")
@property
def area(self):
"""The total area covered by the mesh."""
return (np.abs(self.x_range[1] - self.x_range[0])
* np.abs(self.y_range[1] - self.y_range[0]))
[docs]
def incoming_waves(self, problem: "DiffractionProblem") -> np.ndarray:
"""Free surface elevation of the undisturbed incoming waves
for a given diffraction problem.
Kept for legacy, but not recommended for use.
"""
from capytaine.bem.airy_waves import airy_waves_free_surface_elevation
return airy_waves_free_surface_elevation(self, problem)