Source code for kokiy.axishell

"""Defines an x-axisymmetric shell object.
"""

import numpy as np
from scipy import interpolate

from kokiy.shell_2d import Shell2D

MAX_SPLINE_ORDER = 3
SPLINE_SMOOTHNESS = 0


[docs]class AxiShell(Shell2D): r"""An x-axisymmetric computational shell. Some attributes are based on **u** and **v**, defined as the curvilinear longitudinal (x/r) abscissa and curvilinear azimutal (theta) abscissa respectively. Args: n_azi (int): Number of azimuthal shell points. n_longi (int): Number of longitudinal shell points. angle (float): Range angle of the axicylindrical geometry. ctrl_pts_x (np.array): x-coordinates of the points defining the spline of shape (n,). ctrl_pts_r (np.array): r-coordinates of the points defining the spline of shape (n,). angle_min (float): Minimum angle of the shell. :: (x_n, r_n) _____X_____ ___---- | ----___ Cylindrical system \ | / Example longi/u <=> r \ | / \ | / r - longi/u \ | / ^ \ | (x_0, r_0) | \ _X_ / | \__--- ---__/ X-----> theta - azi/v x ................ ... .. Cylindrical system .. . Example longi/u <=> x/r . . . ................ r . . ^ . ................... | .. | ...................... X-----> x <-- theta - azi/v x/r - longi/u """ geom_type = 'axicyl'
[docs] def __init__(self, n_azi, n_longi, angle, ctrl_pts_x, ctrl_pts_r, angle_min=None): super().__init__(n_azi, n_longi) self.ctrl_pts_x = ctrl_pts_x self.ctrl_pts_r = ctrl_pts_r self.angle = angle self.angle_min = angle_min self._build_shell()
def _build_shell(self): """Builds shell from geometric features. Notes: - Construct a spline used as base for extrusion from control points : tck - Discretise the spline : shell_crest - Compute normal vectors for the 1D shell_crest - Compute r,n_x,n_r-components for 2D shell - Compute theta-components for 2D shell - Compute xyz,n_y,n_z-components for 2D shell """ # Construct Shell Crest shell_crest = _compute_shell_crest(self.ctrl_pts_x, self.ctrl_pts_r, self.shape[1]) # Compute radius and theta matrices of shape (n_azi, n_longi) rot_angle = 0 if self.angle_min is not None: rot_angle = 0.5 * self.angle + self.angle_min min_theta = (rot_angle - 0.5 * self.angle) * np.pi / 180 max_theta = (rot_angle + 0.5 * self.angle) * np.pi / 180 theta_vec = np.linspace(min_theta, max_theta, num=self.shape[0]) self.rad, self.theta = np.meshgrid(shell_crest[1], theta_vec) # Compute xyz matrix of shape (n_azi, n_longi, 3) self.x = np.tile(shell_crest[0], (self.shape[0], 1)) self.y = self.rad * np.cos(self.theta) self.z = self.rad * np.sin(self.theta) # Compute x,y,z,r-normal matrix of shape (n_azi, n_longi) xr_nml_1d = _compute_shellcrest_nml(shell_crest) self.n_r = np.tile(xr_nml_1d[1], (self.shape[0], 1)) self.n_x = np.tile(xr_nml_1d[0], (self.shape[0], 1)) self.n_y = self.n_r * np.cos(self.theta) self.n_z = self.n_r * np.sin(self.theta) # Compute du, dv matrix of shape (n_azi, n_longi) self.du = np.pad(np.sqrt(np.diff(self.x, axis=1) ** 2 + np.diff(self.rad, axis=1) ** 2), ((0, 0), (1, 0)), 'edge') self.dv = self.rad * np.pad(np.diff(self.theta, axis=0), ((1, 0), (0, 0)), 'edge') # Compute abs_curv array of shape (n_longi,) self.abs_curv = self._compute_abs_curv(self.du) # Compute weight intervals in u and v directions array of shape (n_transvers, n_longi) self.dwu, self.dwv = self._compute_weight_interv_adim(self.du, self.dv) # Compute surface nodes array of shape (n_transvers, n_longi) self.surf = self._compute_surf(self.dwu, self.dwv)
[docs] def replicate(self, shape): """Creates a similar instance, but possibly with different shape. """ return AxiShell(*shape, self.angle, self.ctrl_pts_x, self.ctrl_pts_r, angle_min=self.angle_min)
def _compute_shell_crest(ctrl_pts_1, ctrl_pts_2, n): """Build the shell crest of shape (2, self.shape[1]) and respecting controls points. """ # Build crest spline_order = min(len(ctrl_pts_1) - 1, MAX_SPLINE_ORDER) # Generate continuous spline from control points. tck, _ = interpolate.splprep([ctrl_pts_1, ctrl_pts_2], s=SPLINE_SMOOTHNESS, k=spline_order) unew = np.linspace(0, 1, num=n) # Generate discrete spline # Numpy Array of dim (2, self.shape[1]) [x,r] / [x,y] shell_crest = np.asarray(interpolate.splev(unew, tck)) return shell_crest def _compute_shellcrest_nml(shell_crest): """Computes shell crest normals. """ nml_vect = np.roll(np.diff(shell_crest), 1, axis=0) nml_vect /= np.linalg.norm(nml_vect, axis=0) nml_vect[0, :] *= -1 nml_vect = np.pad(nml_vect, ((0, 0), (0, 1)), mode='edge') return nml_vect