Source code for g3d.mesh.modules.single_block_cylinder

"""single-block cylinder mesh module"""
from typing import Any

from g3d.defs import G3DWorld
from g3d.defs import G3DDisplay

from g3d.mesh.modules import BlockModule

from g3d.defs import NodeDistribution
from g3d.defs import Direction
from g3d.defs import AngleType
from g3d.defs import INTFTypes
from g3d.defs import DIMMode
from g3d.defs import BlockFace
from g3d.defs import FaceOrientation

from g3d.mesh.geo import Coord
from g3d.mesh.geo import Edge
from g3d.mesh.geo import Block


[docs] class SingleBlockCylinderModule(BlockModule): def __init__(self, *args: Any, **kwargs: Any) -> None: super().__init__(*args, **kwargs) self._cylinder_radius = 1. self._o_grid_radius = 1.2 self._outer_box_size = 6. self._n_cells_o_grid = 10 self._n_cells_external = 10 self._wall_cell_height = 0.0001 self._n_data_points = 36 self._o_grid_scale_factor = 0. self._o_grid_shape_factor = 0.2 self._o_grid_stretch_rate = 4.0 self._cylinder_length = 1. self._inner_wake_cell_size = 0.0001 self._outer_wake_cell_size = 0.001 self._n_cells_half_outlet = 30 self._n_cells_half_freestream = 15 self._n_cells_half_inlet = 10 self._do_not_smooth_o_grid = True
[docs] def set_from_key_value(self, key: str, value: Any) -> bool: if super().set_from_key_value(key, value): return True elif key == 'cylinder_radius': self._cylinder_radius = value return True elif key == 'o_grid_radius': self._o_grid_radius = value return True elif key == 'outer_box_size': self._outer_box_size = value return True elif key == 'wall_cell_height': self._wall_cell_height = value return True elif key == 'n_data_points': self._n_data_points = value return True elif key == 'o_grid_scale_factor': self._o_grid_scale_factor = value return True elif key == 'o_grid_shape_factor': self._o_grid_shape_factor = value return True elif key == 'o_grid_stretch_rate': self._o_grid_stretch_rate = value return True elif key == 'cylinder_length': self._cylinder_length = value return True elif key == 'inner_wake_cell_size': self._inner_wake_cell_size = value return True elif key == 'outer_wake_cell_size': self._outer_wake_cell_size = value return True elif key == 'n_cells_half_outlet': self._n_cells_half_outlet = value return True elif key == 'n_cells_half_freestream': self._n_cells_half_freestream = value return True elif key == 'n_cells_half_inlet': self._n_cells_half_inlet = value return True elif key == 'do_not_smooth_o_grid': self._do_not_smooth_o_grid = value return True return False
@property def cylinder_radius(self) -> float: """ :return: """ return self._cylinder_radius @cylinder_radius.setter def cylinder_radius(self, val: float) -> None: self._cylinder_radius = val @property def o_grid_radius(self) -> float: """ :return: """ return self._o_grid_radius @o_grid_radius.setter def o_grid_radius(self, val: float) -> None: self._o_grid_radius = val @property def outer_box_size(self) -> float: """ :return: """ return self._outer_box_size @outer_box_size.setter def outer_box_size(self, val: float) -> None: self._outer_box_size = val @property def n_cells_o_grid(self) -> int: """ :return: """ return self._n_cells_o_grid @n_cells_o_grid.setter def n_cells_o_grid(self, val: int) -> None: self._n_cells_o_grid = val @property def n_cells_external(self) -> int: """ :return: """ return self._n_cells_external @n_cells_external.setter def n_cells_external(self, val: int) -> None: self._n_cells_external = val @property def wall_cell_height(self) -> float: """ :return: """ return self._wall_cell_height @wall_cell_height.setter def wall_cell_height(self, val: float) -> None: self._wall_cell_height = val @property def n_data_points(self) -> int: """ :return: """ return self._n_data_points @n_data_points.setter def n_data_points(self, val: int) -> None: self._n_data_points = val @property def o_grid_scale_factor(self) -> float: """ :return: """ return self._o_grid_scale_factor @o_grid_scale_factor.setter def o_grid_scale_factor(self, val: float) -> None: self._o_grid_scale_factor = val @property def o_grid_shape_factor(self) -> float: """ :return: """ return self._o_grid_shape_factor @o_grid_shape_factor.setter def o_grid_shape_factor(self, val: float) -> None: """ :param val: """ self._o_grid_shape_factor = val @property def o_grid_stretch_rate(self) -> float: """ :return: """ return self._o_grid_stretch_rate @o_grid_stretch_rate.setter def o_grid_stretch_rate(self, val: float) -> None: self._o_grid_stretch_rate = val @property def cylinder_length(self) -> float: """ :return: """ return self._cylinder_length @cylinder_length.setter def cylinder_length(self, val: float) -> None: self._cylinder_length = val @property def inner_wake_cell_size(self) -> float: """ :return: """ return self._inner_wake_cell_size @inner_wake_cell_size.setter def inner_wake_cell_size(self, val: float) -> None: self._inner_wake_cell_size = val @property def outer_wake_cell_size(self) -> float: """ :return: """ return self._outer_wake_cell_size @outer_wake_cell_size.setter def outer_wake_cell_size(self, val: float) -> None: self._outer_wake_cell_size = val @property def n_cells_half_outlet(self) -> int: """ :return: """ return self._n_cells_half_outlet @n_cells_half_outlet.setter def n_cells_half_outlet(self, val: int) -> None: self._n_cells_half_outlet = val @property def n_cells_half_freestream(self) -> int: """ :return: """ return self._n_cells_half_freestream @n_cells_half_freestream.setter def n_cells_half_freestream(self, val: int) -> None: self._n_cells_half_freestream = val @property def n_cells_half_inlet(self) -> int: """ :return: """ return self._n_cells_half_inlet @n_cells_half_inlet.setter def n_cells_half_inlet(self, val: int) -> None: self._n_cells_half_inlet = val @property def do_not_smooth_o_grid(self) -> bool: """ :return: """ return self._do_not_smooth_o_grid @do_not_smooth_o_grid.setter def do_not_smooth_o_grid(self, val: bool) -> None: self._do_not_smooth_o_grid = val def _generate_mesh(self) -> None: R = self._cylinder_radius H = self._outer_box_size if self._o_grid_scale_factor == 0.: self._o_grid_scale_factor = self._o_grid_radius / R n0 = self._n_cells_o_grid + 1 n1 = self._n_cells_external + 1 # ===================================================================== # BLOCK NODE COUNTS # ===================================================================== ni1 = (2 * self._n_cells_half_outlet + 4 * self._n_cells_half_freestream + 2 * self._n_cells_half_inlet + 1) nj1 = n0 + n1 - 1 # ===================================================================== # Block 1: cylinder o-grid and external region # ===================================================================== b1 = Block(ni1, nj1, self._nk3D) self.add_Block(b1) c11 = Coord(R, 0.0, 0.0, spacing=self._inner_wake_cell_size) c12 = Coord(c11).scale(self._o_grid_scale_factor) e11 = self.circular_edge(c11, ni1, direction=Direction.X_DIRECTION, N=self._n_data_points) b1.add_Edge(e11, [1, 1, 1, 1, ni1]) e12 = Edge(e11) e12.scale(self._o_grid_scale_factor) b1.add_Edge(e12, [1, n0, 1, 1, ni1]) c11m = Coord(c11, ialt=AngleType.IALT_1, alpha=0., beta=0., shape_factor=self._o_grid_shape_factor, spacing=self._wall_cell_height) e13 = Edge(n0, c11m, c12, distribute=NodeDistribution.CURVE_3, stretch_rate=self._o_grid_stretch_rate) b1.add_Edge(e13, [1, 1, 1, 3, n0]) e14 = Edge(e13) b1.add_Edge(e14, [ni1, 1, 1, 3, n0]) # outer domain coordinates c31 = Coord(H / 2., 0.0, 0.0) c32 = Coord(H / 2., -H / 2., 0.0) c33 = Coord(-H / 2., -H / 2., 0.0) c34 = Coord(-H / 2., H / 2., 0.0) c35 = Coord(H / 2., H / 2., 0.0) c36 = Coord(c31) # ===================================================================== # populate outer block edge (I-direction) # ===================================================================== n_start = 1 n_edge = self._n_cells_half_outlet + 1 c31m = Coord(c31, spacing=self._outer_wake_cell_size) e17 = Edge(n_edge, c31m, c32, distribute=NodeDistribution.CURVE_5, stretch_rate=2.) b1.add_Edge(e17, [n_start, nj1, 1, 1, n_edge]) n_start += n_edge - 1 n_edge = 2 * self._n_cells_half_freestream + 1 e18 = Edge(n_edge, c32, c33, distribute=NodeDistribution.CURVE_2, stretch_rate=0.) b1.add_Edge(e18, [n_start, nj1, 1, 1, n_edge]) n_start += n_edge - 1 n_edge = 2 * self._n_cells_half_inlet + 1 e19 = Edge(n_edge, c33, c34, distribute=NodeDistribution.CURVE_2, stretch_rate=0.) b1.add_Edge(e19, [n_start, nj1, 1, 1, n_edge]) n_start += n_edge - 1 n_edge = 2 * self._n_cells_half_freestream + 1 e20 = Edge(n_edge, c34, c35, distribute=NodeDistribution.CURVE_2, stretch_rate=0.) b1.add_Edge(e20, [n_start, nj1, 1, 1, n_edge]) n_start = ni1 n_edge = self._n_cells_half_outlet + 1 c36m = Coord(c36, spacing=self._outer_wake_cell_size) e21 = Edge(n_edge, c36m, c35, distribute=NodeDistribution.CURVE_5, stretch_rate=2.) b1.add_Edge(e21, [n_start, nj1, 1, 2, n_edge]) # ===================================================================== # block outer end edges (J-direction) # ===================================================================== h1 = e13.h1 c12m = Coord(c12, spacing=h1) e15 = Edge(n1, c12m, c31, distribute=NodeDistribution.CURVE_5, stretch_rate=2.) b1.add_Edge(e15, [1, n0, 1, 3, n1]) e16 = Edge(e15) b1.add_Edge(e16, [ni1, n0, 1, 3, n1]) # ===================================================================== # control edges # ===================================================================== shape_factor = 0.5 * (H - self._o_grid_scale_factor * self._cylinder_radius) # outer domain (270 degrees) nic = self._n_cells_half_outlet + self._n_cells_half_freestream c411 = Coord(e11.get_Coord(nic)) c412 = Coord(e12.get_Coord(nic), spacing=h1) c413 = e18.get_Coord(self._n_cells_half_freestream) alfa, beta = c411.get_angle(c412, ialt=AngleType.IALT_1, angle_dim=AngleType.DEGREES) c412.set(ialt=AngleType.IALT_1, alpha=alfa, beta=beta, shape_factor=shape_factor, spacing=h1) c413.set(ialt=AngleType.IALT_1, alpha=270., beta=0., shape_factor=shape_factor) e22 = Edge(n1, c412, c413, distribute=NodeDistribution.CURVE_4, stretch_rate=0.5) b1.add_Edge(e22, [nic + 1, n0, 1, 3, n1]) # outer domain (180 degrees) nic += self._n_cells_half_freestream + self._n_cells_half_inlet c422 = Coord(e12.get_Coord(nic), spacing=h1) c423 = e19.get_Coord(self._n_cells_half_inlet) e23 = Edge(n1, c422, c423, distribute=NodeDistribution.CURVE_5, stretch_rate=2.) b1.add_Edge(e23, [nic + 1, n0, 1, 3, n1]) # outer domain (90 degrees) nic += self._n_cells_half_inlet + self._n_cells_half_freestream c431 = Coord(e11.get_Coord(nic)) c432 = Coord(e12.get_Coord(nic), spacing=h1) c433 = e20.get_Coord(self._n_cells_half_freestream) alfa, beta = c431.get_angle(c432, ialt=AngleType.IALT_1, angle_dim=AngleType.DEGREES) c432.set(ialt=AngleType.IALT_1, alpha=alfa, beta=beta, shape_factor=shape_factor, spacing=h1) c433.set(ialt=AngleType.IALT_1, alpha=90., beta=0., shape_factor=shape_factor) e24 = Edge(n1, c432, c433, distribute=NodeDistribution.CURVE_4, stretch_rate=0.5) b1.add_Edge(e24, [nic + 1, n0, 1, 3, n1]) # outer domain (315 degrees) nic = self._n_cells_half_outlet c441 = Coord(e11.get_Coord(nic)) c442 = Coord(e12.get_Coord(nic), spacing=h1) c443 = Coord(e18.start) alfa, beta = c441.get_angle(c442, ialt=AngleType.IALT_1, angle_dim=AngleType.DEGREES) c442.set(ialt=AngleType.IALT_1, alpha=alfa, beta=beta, shape_factor=shape_factor, spacing=h1) c443.set(ialt=AngleType.IALT_1, alpha=315., beta=0., shape_factor=shape_factor) e25 = Edge(n1, c442, c443, distribute=NodeDistribution.CURVE_4, stretch_rate=0.5) b1.add_Edge(e25, [nic + 1, n0, 1, 3, n1]) # outer domain (225 degrees) nic += 2 * self._n_cells_half_freestream c451 = Coord(e11.get_Coord(nic)) c452 = Coord(e12.get_Coord(nic), spacing=h1) c453 = Coord(e19.start) alfa, beta = c451.get_angle(c452, ialt=AngleType.IALT_1, angle_dim=AngleType.DEGREES) c452.set(ialt=AngleType.IALT_1, alpha=alfa, beta=beta, shape_factor=shape_factor, spacing=h1) c453.set(ialt=AngleType.IALT_1, alpha=225., beta=0., shape_factor=shape_factor) e26 = Edge(n1, c452, c453, distribute=NodeDistribution.CURVE_4, stretch_rate=0.5) b1.add_Edge(e26, [nic + 1, n0, 1, 3, n1]) # outer domain (135 degrees) nic += 2 * self._n_cells_half_inlet c461 = Coord(e11.get_Coord(nic)) c462 = Coord(e12.get_Coord(nic), spacing=h1) c463 = Coord(e20.start) alfa, beta = c461.get_angle(c462, ialt=AngleType.IALT_1, angle_dim=AngleType.DEGREES) c462.set(ialt=AngleType.IALT_1, alpha=alfa, beta=beta, shape_factor=shape_factor, spacing=h1) c463.set(ialt=AngleType.IALT_1, alpha=135., beta=0., shape_factor=shape_factor) e27 = Edge(n1, c462, c463, distribute=NodeDistribution.CURVE_4, stretch_rate=0.5) b1.add_Edge(e27, [nic + 1, n0, 1, 3, n1]) # outer domain (45 degrees) nic += 2 * self._n_cells_half_freestream c471 = Coord(e11.get_Coord(nic)) c472 = Coord(e12.get_Coord(nic), spacing=h1) c473 = Coord(e21.end) alfa, beta = c471.get_angle(c472, ialt=AngleType.IALT_1, angle_dim=AngleType.DEGREES) c472.set(ialt=AngleType.IALT_1, alpha=alfa, beta=beta, shape_factor=shape_factor, spacing=h1) c473.set(ialt=AngleType.IALT_1, alpha=45., beta=0., shape_factor=shape_factor) e28 = Edge(n1, c472, c473, distribute=NodeDistribution.CURVE_4, stretch_rate=0.5) b1.add_Edge(e28, [nic + 1, n0, 1, 3, n1]) # ===================================================================== # fill KLOW plane # ===================================================================== # fill o-grid b1.fill_Face([1, 1, 1, 1, 3, ni1, n0]) # outer domain - segment 1 ni_start = 1 ni_delta = self._n_cells_half_outlet + 1 b1.fill_Face([ni_start, n0, 1, 1, 3, ni_delta, n1]) # outer domain - segment 2 ni_start += ni_delta - 1 ni_delta = self._n_cells_half_freestream + 1 b1.fill_Face([ni_start, n0, 1, 1, 3, ni_delta, n1]) # outer domain - segment 3 ni_start += ni_delta - 1 ni_delta = self._n_cells_half_freestream + 1 b1.fill_Face([ni_start, n0, 1, 1, 3, ni_delta, n1]) # outer domain - segment 4 ni_start += ni_delta - 1 ni_delta = self._n_cells_half_inlet + 1 b1.fill_Face([ni_start, n0, 1, 1, 3, ni_delta, n1]) # outer domain - segment 5 ni_start += ni_delta - 1 ni_delta = self._n_cells_half_inlet + 1 b1.fill_Face([ni_start, n0, 1, 1, 3, ni_delta, n1]) # outer domain - segment 6 ni_start += ni_delta - 1 ni_delta = self._n_cells_half_freestream + 1 b1.fill_Face([ni_start, n0, 1, 1, 3, ni_delta, n1]) # outer domain - segment 7 ni_start += ni_delta - 1 ni_delta = self._n_cells_half_freestream + 1 b1.fill_Face([ni_start, n0, 1, 1, 3, ni_delta, n1]) # outer domain - segment 8 ni_start += ni_delta - 1 ni_delta = self._n_cells_half_outlet + 1 b1.fill_Face([ni_start, n0, 1, 1, 3, ni_delta, n1]) def _generate_mesh_post(self) -> int: self._smooth() self._extrude_mesh() return super()._generate_mesh_post() def _extrude_mesh(self) -> None: g3d_disp = G3DDisplay() # extrude mesh in K-direction if not g3d_disp.silent: g3d_disp.header('extruding 2D mesh plane in K-direction') e_min = Coord(0., 0., 0.) e_max = Coord(0., 0., self._cylinder_length) e_ext = Edge(self._nk3D, e_min, e_max, distribute=NodeDistribution.CURVE_2, stretch_rate=0.) for b in self._blocks: b.extrude_Face(b.get_Face(BlockFace.KLOW, FaceOrientation.INWARD_FACING_NORMAL), e_ext) def _smooth(self) -> None: if self._smooth_faces: g3d_disp = G3DDisplay() if not g3d_disp.silent: g3d_disp.header('smoothing mesh (surface smoother)') b1 = self._blocks[0] if self._do_not_smooth_o_grid: im = 1 i0 = 1 j0 = self._n_cells_o_grid + 1 k0 = 1 idir = 1 jdir = 3 npi = b1.ni npj = self._n_cells_external + 1 self.add_smooth_face([im, i0, j0, k0, idir, jdir, npi, npj]) self.add_smooth_face_glue([im, 1, j0, 1, 5, 3, 1, npj], [im, b1.ni, j0, 1, 5, 3, 1, npj]) else: self.add_smooth_face(b1.get_Face(BlockFace.KLOW)) faceA = b1.get_Face(BlockFace.ILOW, FaceOrientation.OUTWARD_FACING_NORMAL) faceB = b1.get_Face(BlockFace.IHIGH, FaceOrientation.INWARD_FACING_NORMAL) self.add_smooth_face_glue(faceA, faceB) self.smooth(self._n_smooth) def _add_boundaries(self) -> None: g3d_world = G3DWorld() b1 = self._blocks[0] # block interfaces faceA = b1.get_Face(BlockFace.ILOW, FaceOrientation.OUTWARD_FACING_NORMAL) faceB = b1.get_Face(BlockFace.IHIGH, FaceOrientation.INWARD_FACING_NORMAL) self.add_Intf(faceA, faceB, intf_type=INTFTypes.INTERFACES) # block end faces (K-direction) if g3d_world.options.dim_mode == DIMMode.G3D: faceA = b1.get_Face(BlockFace.KLOW, FaceOrientation.OUTWARD_FACING_NORMAL) faceA.delta.z = self._cylinder_length faceB = b1.get_Face(BlockFace.KHIGH, FaceOrientation.INWARD_FACING_NORMAL) self.add_Intf(faceA, faceB, intf_type=INTFTypes.TRANSPERINT) # populate outer block edge n_start = 1 n_edge = self._n_cells_half_outlet + 1 self.add_IO([1, n_start, b1.nj, 1, 1, 5, n_edge, self._nk3D], tag='outlet') n_start += n_edge - 1 n_edge = 2 * self._n_cells_half_freestream + 1 self.add_IO([1, n_start, b1.nj, 1, 1, 5, n_edge, self._nk3D], tag='freestream') n_start += n_edge - 1 n_edge = 2 * self._n_cells_half_inlet + 1 self.add_IO([1, n_start, b1.nj, 1, 1, 5, n_edge, self._nk3D], tag='inlet') n_start += n_edge - 1 n_edge = 2 * self._n_cells_half_freestream + 1 self.add_IO([1, n_start, b1.nj, 1, 1, 5, n_edge, self._nk3D], tag='freestream') n_start += n_edge - 1 n_edge = self._n_cells_half_outlet self.add_IO([1, n_start, b1.nj, 1, 1, 5, n_edge, self._nk3D], tag='outlet') # cylinder wall self.add_BC(b1.get_Face(BlockFace.JLOW), tag='cylinder')