Source code for g3d.flow.placeholders.fluxmolecule

"""Flux molecule placeholder (FMP class definition)"""
from typing import Any, Union, Tuple, TextIO

import os

if os.environ.get('__USE_CUDA', '0') == '1':
    import cupy as np
    from cupy import ndarray
else:
    import numpy as np
    from numpy import ndarray

from g3d.defs import G3DWorld
from g3d.defs import DIMMode
from g3d.defs import FMPTypes
from g3d.defs import G3DEntity
from g3d.defs import FunctionByPass


[docs] class FMP(G3DEntity): """Definition of class FMP: Flux Molecule Pointers - cell/node pointers and metrics data container""" def __init__(self, *args: Any, **kwargs: Any) -> None: self._size = 0 self._type = FMPTypes.UNDEFINED self._fctj = 0.25 * np.ones(self._size) self._fctk = 0.25 * np.ones(self._size) self._kc = np.zeros((self._size, 12), dtype=np.int64) self._kp = np.zeros((self._size, 12), dtype=np.int64) self._sl = np.zeros(self._size) self._voli = np.ones(self._size) self._s = np.zeros((self._size, 3)) self._sx = np.zeros((self._size, 3)) self._sy = np.zeros((self._size, 3)) self._sz = np.zeros((self._size, 3)) self._si = np.zeros((self._size, 3)) self._y_norm = np.zeros(self._size) self._tmp = np.zeros(self._size) super().__init__(*args, **kwargs) self.allocate(**kwargs) def _set_from_args(self, *args: Any, **kwargs: Any) -> ndarray: bps = self._get_function_evaluate_status(**kwargs) if bps is FunctionByPass.SELF: args_stat = np.ones(len(args)) else: args_stat = super()._set_from_args(*args) if bps in [FunctionByPass.EVALUATE, FunctionByPass.SELF]: if np.sum(args_stat) == 1: size_set = False for i in range(len(args)): if args_stat[i] == 1: arg = args[i] if type(arg) is int and not size_set: args_stat[i] = 0 self._size = arg size_set = True return args_stat def _set_default(self) -> None: super()._set_default() self._tag = 'g3d_flux_molecule'
[docs] def set_from_key_value(self, key: str, value: Any) -> bool: """Sets data from key-value pair input Parameters ---------- key: str : keyword valid class-specific keywords: 'size', 'type' value: Any : value corresponding to keyword Returns ------- bool status - True if key is found in list of valid keywords """ if super().set_from_key_value(key, value): return True elif key == 'size': self._size = value return True elif key == 'type': self._type = value return True return False
[docs] def allocate(self, **kwargs: Any) -> None: """Allocates data storage arrays Parameters ---------- **kwargs: Any : keyword-value pairs, see :func:'set_from_key_value', optional input """ if len(kwargs): self.set(**kwargs) self.__de_allocate() if self._size > 0: self._fctj = 0.25 * np.ones(self._size) self._fctk = 0.25 * np.ones(self._size) self._kc = np.zeros((self._size, 12), dtype=np.int64) self._kp = np.zeros((self._size, 12), dtype=np.int64) self._sl = np.zeros(self._size) self._voli = np.ones(self._size) self._s = np.zeros((self._size, 3)) self._sx = np.zeros((self._size, 3)) self._sy = np.zeros((self._size, 3)) self._sz = np.zeros((self._size, 3)) self._si = np.zeros((self._size, 3))
@property def size(self) -> int: """Placeholder size Returns ------- int size """ return self._size @size.setter def size(self, val: int) -> None: self._size = val @property def type(self) -> Any: """Placeholder type Returns ------- FMPTypes enum describing placeholder type """ return self._type @type.setter def type(self, val: Any) -> None: if type(val) is FMPTypes: self._type = val @property def fctj(self) -> ndarray: """Face local j-direction multiplication factor Returns ------- ndarray local j-direction factors for all placeholder faces """ return self._fctj @property def fctk(self) -> ndarray: """Face local k-direction multiplication factor Returns ------- ndarray local k-direction factors for all placeholder faces """ return self._fctk @property def kc(self) -> ndarray: """Cell index pointers for flux molecule cells (12 per molecule) Returns ------- ndarray cell pointers """ return self._kc @property def kp(self) -> ndarray: """Node index pointers for flux molecule cells (12 per molecule) Returns ------- ndarray node pointers """ return self._kp @property def sl(self) -> ndarray: """Face area for all flux molecules (central molecule face) Returns ------- ndarray: face area array """ return self._sl @property def voli(self) -> ndarray: """Inverse of flux molecule volume Returns ------- ndarray inverse volume array """ return self._voli @property def s(self) -> ndarray: """:return:""" return self._s @property def sx(self) -> ndarray: """:return:""" return self._sx @property def sy(self) -> ndarray: """:return:""" return self._sy @property def sz(self) -> ndarray: """:return:""" return self._sz @property def si(self) -> ndarray: """:return:""" return self._si @property def y_norm(self) -> ndarray: """Wall-normal vector Returns ------- ndarray wall-normal vector (n_x, n_y, n_z) """ return self._y_norm @property def tmp(self) -> ndarray: """Temporary storage array Returns ------- ndarray temporary storage array access """ return self._tmp def __de_allocate(self) -> None: self._fctj = [] self._fctk = [] self._kc = np.zeros((12,), dtype=np.int64) self._kp = np.zeros((12,), dtype=np.int64) self._sl = [] self._voli = [] self._s = np.zeros((3,)) self._sx = np.zeros((3,)) self._sy = np.zeros((3,)) self._sz = np.zeros((3,)) self._si = np.zeros((3,)) self._y_norm = [] self._tmp = []
[docs] def allocate_tmp_arrays(self, N: int = 1) -> None: """Allocates arrays for temporary data storage Parameters ---------- N: int : number of tmp storage arrays (Default value = 1) """ self._tmp = np.zeros((self._size, N))
[docs] def get_tmp_storage(self, col: int = 0) -> ndarray: """Gets access to temporary storage array Parameters ---------- col: int : column in temporary storage matrix (Default value = 0) Returns ------- ndarray temporary storage array """ return self._tmp[:, col]
[docs] def set_pointers(self, idx: int, kp: Union[ndarray, list[int]], kc: Union[ndarray, list[int]]) -> None: """Populate cell and node pointers using provided arrays Parameters ---------- idx: int : face index kp: ndarray or list[int] : node indices (12 nodes per molecule) kc: ndarray or list[int] : cell indices (12 cells per molecule) """ self._kp[idx, :] = kp[:] self._kc[idx, :] = kc[:]
[docs] def set_factors(self, idx: int, fctj: float, fctk: float) -> None: """Update flux molecule weight factors Weight factors are needed for calculation of cell face gradients and diffusive fluxes. The provided weight factors represents the flux molecule local j- and k-directions, respectively. The local i-direction of a flux molecule is always aligned with the center face normal (i.e. in the convective molecule direction) Parameters ---------- idx: int : cell index fctj: float : weight factor local j-direction fctk: float : weight factor local k-direction """ self._fctj[idx] = fctj self._fctk[idx] = fctk
[docs] def set_data(self, idx: int, kp: Union[ndarray, list[int]], kc: Union[ndarray, list[int]], fctj: float, fctk: float) -> None: """Set flux molecule data (cell and node pointers and weight factors) See documentation of :func:'set_pointers' and :func:'set_factors' Parameters ---------- idx: int : flux molecule index kp: ndarray or list[int] : node indices (12 nodes per molecule) kc: ndarray or list[int] : cell indices (12 cells per molecule) fctj: float : weight factor local j-direction fctk: float : weight factor local k-direction """ self.set_pointers(idx, kp, kc) self.set_factors(idx, fctj, fctk)
[docs] def get_pointers(self, idx: int = None) -> Tuple[ndarray, ndarray]: """Gets node and cell pointers for all defined flux molecules or a specific flux molecule. Parameters ---------- idx: int : flux molecule index (Default value = None) Returns ------- tuple node and cell pointers for a single flux molecule (if index is specified) or for all defined flux molecules in container (kp, kc) where kp and kc both are arrays """ if idx is None: return self._kp, self._kc else: return self._kp[idx, :], self._kc[idx, :]
[docs] def get_factors(self, idx: int = None) -> Union[Tuple[float, float], Tuple[ndarray, ndarray]]: """Gets weight factors for all defined flux molecules or a specific flux molecule. Parameters ---------- idx: int : flux molecule index (Default value = None) Returns ------- tuple weight factors in local j- and k-directions for all defined flux molecules in container or one specific flux molecule (if flux molecule index is provided) """ if idx is None: return self._fctj, self._fctk else: return self._fctj[idx], self._fctk[idx]
[docs] def get_conv_metrics(self, idx: int = None) -> Union[Tuple[float, float], Tuple[ndarray, ndarray]]: """Get metrics data used for convective flux calculations for all flux molecules or for a specific flux molecule Parameters ---------- idx: int : flux molecule index (Default value = None) Returns ------- tuple face area """ if idx is None: return self._s, self._sl else: return self._s[idx, :], self._sl[idx]
[docs] def get_diff_metrics(self, idx: int = None) -> Union[Tuple[float, ...], Tuple[ndarray, ...]]: """Get metrics data used for diffusive flux calculations for all flux molecules or for a specific flux molecule Parameters ---------- idx: int : flux molecule index (Default value = None) Returns ------- tuple """ if idx is None: return self._sx, self._sy, self._sz, self._si, self._voli else: return self._sx[idx, :], self._sy[idx, :], self._sz[idx, :], self._si[idx, :], self._voli[idx]
[docs] def get_wall_normal(self, idx: int = None) -> Union[float, ndarray]: """Gets wall-normal for all flux molecules or for a specific flux molecule Parameters ---------- idx: int : flux molecule index (Default value = None) Returns ------- float or ndarray wall-normal vector """ if idx is None: return self._y_norm else: return self._y_norm[idx]
[docs] def print(self, idx: int = None) -> None: """Prints flux molecule data (dell pointers, node pointers, and weight factors) for all flux molecules or for a specific flux molecule Parameters ---------- idx: int : flux molecule index (Default value = None) """ if idx is None: for i in range(self._size): self.print(i) else: print(self._fctj[idx], self._fctk[idx]) print(self._kp[idx][:]) print(self._kc[idx][:])
[docs] def update_factors(self, idx: int, mim: int, mip: int, mjm: int, mjp: int) -> None: """Update flux molecule weight factors Parameters ---------- idx : int : flux molecule index mim : int : number of flux molecule cells in negative local i-direction (0 at low-i boundary) mip : int : number of flux molecule cells in positive local i-direction (0 at high-i boundary) mjm : int : number of flux molecule cells in negative local j-direction (0 at low-j boundary) mjp : int : number of flux molecule cells in positive local j-direction (0 at high-j boundary) """ self._fctj[idx] = 0.25 self._fctk[idx] = 0.25 if mim == 0: self._fctj[idx] += 0.25 if mip == 0: self._fctj[idx] += 0.25 if mjm == 0: self._fctk[idx] += 0.25 if mjp == 0: self._fctk[idx] += 0.25 if self._fctj[idx] == 0.75: self._fctj[idx] = 0.0 if self._fctk[idx] == 0.75: self._fctk[idx] = 0.0
[docs] def update_block_interface_factors(self, idx: int, mim: int, mip: int, mjm: int, mjp: int) -> None: """Update flux molecule weight factors for mesh block interfaces Parameters ---------- idx : int : flux molecule index mim : int : number of flux molecule cells in negative local i-direction (0 at low-i boundary) mip : int : number of flux molecule cells in positive local i-direction (0 at high-i boundary) mjm : int : number of flux molecule cells in negative local j-direction (0 at low-j boundary) mjp : int : number of flux molecule cells in positive local j-direction (0 at high-j boundary) """ self._fctj[idx] = 0.25 self._fctk[idx] = 0.25 if mim == 0 and mip == 0: self._fctj[idx] = 0.0 elif mim == 0 or mip == 0: self._fctj[idx] = 0.5 if mjm == 0 and mjp == 0: self._fctk[idx] = 0.0 elif mjm == 0 or mjp == 0: self._fctk[idx] = 0.5
[docs] def update_metrics(self, x: ndarray, y: ndarray, z: ndarray) -> None: """Update flux molecule metrics data Parameters ---------- x : ndarray : x-coordinate vector y : ndarray : y-coordinate vector z : ndarray : z-coordinate vector """ g3d_world = G3DWorld() idx1 = 0 idx2 = self._size self._s[idx1:idx2, 0] = 0.5 * ((y[self._kp[idx1:idx2, 3 + 4]] - y[self._kp[idx1:idx2, 0 + 4]]) * (z[self._kp[idx1:idx2, 2 + 4]] - z[self._kp[idx1:idx2, 1 + 4]]) - (z[self._kp[idx1:idx2, 3 + 4]] - z[self._kp[idx1:idx2, 0 + 4]]) * (y[self._kp[idx1:idx2, 2 + 4]] - y[self._kp[idx1:idx2, 1 + 4]])) self._s[idx1:idx2, 1] = 0.5 * ((z[self._kp[idx1:idx2, 3 + 4]] - z[self._kp[idx1:idx2, 0 + 4]]) * (x[self._kp[idx1:idx2, 2 + 4]] - x[self._kp[idx1:idx2, 1 + 4]]) - (x[self._kp[idx1:idx2, 3 + 4]] - x[self._kp[idx1:idx2, 0 + 4]]) * (z[self._kp[idx1:idx2, 2 + 4]] - z[self._kp[idx1:idx2, 1 + 4]])) self._s[idx1:idx2, 2] = 0.5 * ((x[self._kp[idx1:idx2, 3 + 4]] - x[self._kp[idx1:idx2, 0 + 4]]) * (y[self._kp[idx1:idx2, 2 + 4]] - y[self._kp[idx1:idx2, 1 + 4]]) - (y[self._kp[idx1:idx2, 3 + 4]] - y[self._kp[idx1:idx2, 0 + 4]]) * (x[self._kp[idx1:idx2, 2 + 4]] - x[self._kp[idx1:idx2, 1 + 4]])) if g3d_world.options.dim_mode is DIMMode.G2D_AXISYMM: r = 0.25 * (y[self._kp[idx1:idx2, 0 + 4]] + y[self._kp[idx1:idx2, 1 + 4]] + y[self._kp[idx1:idx2, 2 + 4]] + y[self._kp[idx1:idx2, 3 + 4]]) self._s[idx1:idx2, 0] = r * self._s[idx1:idx2, 0] self._s[idx1:idx2, 1] = r * self._s[idx1:idx2, 1] self._s[idx1:idx2, 2] = r * self._s[idx1:idx2, 2] self._sl[idx1:idx2] = (self._s[idx1:idx2, 0] ** 2 + self._s[idx1:idx2, 1] ** 2 + self._s[ idx1:idx2, 2] ** 2) ** 0.5
[docs] def update_diff_metrics(self, x: ndarray, y: ndarray, z: ndarray, n_faces: int = 0, idx_start: int = 0) -> None: """Update flux molecule metrics data for diffusive flux calculations Parameters ---------- x: ndarray : x-coordinate vector y: ndarray : y-coordinate vector z: ndarray : z-coordinate vector n_faces: int : number of faces (Default value = 0) idx_start: int : index of first face (Default value = 0) """ g3d_world = G3DWorld() if n_faces == 0: n_faces = self._size - idx_start idx1 = idx_start idx2 = idx_start + n_faces xi = .125 * (x[self._kp[idx1:idx2, 8]] + x[self._kp[idx1:idx2, 9]] + x[self._kp[idx1:idx2, 10]] + x[self._kp[idx1:idx2, 11]] - x[self._kp[idx1:idx2, 0]] - x[self._kp[idx1:idx2, 1]] - x[self._kp[idx1:idx2, 2]] - x[self._kp[idx1:idx2, 3]]) yi = .125 * (y[self._kp[idx1:idx2, 8]] + y[self._kp[idx1:idx2, 9]] + y[self._kp[idx1:idx2, 10]] + y[self._kp[idx1:idx2, 11]] - y[self._kp[idx1:idx2, 0]] - y[self._kp[idx1:idx2, 1]] - y[self._kp[idx1:idx2, 2]] - y[self._kp[idx1:idx2, 3]]) zi = .125 * (z[self._kp[idx1:idx2, 8]] + z[self._kp[idx1:idx2, 9]] + z[self._kp[idx1:idx2, 10]] + z[self._kp[idx1:idx2, 11]] - z[self._kp[idx1:idx2, 0]] - z[self._kp[idx1:idx2, 1]] - z[self._kp[idx1:idx2, 2]] - z[self._kp[idx1:idx2, 3]]) xj = .5 * (x[self._kp[idx1:idx2, 5]] + x[self._kp[idx1:idx2, 7]] - x[self._kp[idx1:idx2, 4]] - x[self._kp[idx1:idx2, 6]]) yj = .5 * (y[self._kp[idx1:idx2, 5]] + y[self._kp[idx1:idx2, 7]] - y[self._kp[idx1:idx2, 4]] - y[self._kp[idx1:idx2, 6]]) zj = .5 * (z[self._kp[idx1:idx2, 5]] + z[self._kp[idx1:idx2, 7]] - z[self._kp[idx1:idx2, 4]] - z[self._kp[idx1:idx2, 6]]) xk = .5 * (x[self._kp[idx1:idx2, 6]] + x[self._kp[idx1:idx2, 7]] - x[self._kp[idx1:idx2, 4]] - x[self._kp[idx1:idx2, 5]]) yk = .5 * (y[self._kp[idx1:idx2, 6]] + y[self._kp[idx1:idx2, 7]] - y[self._kp[idx1:idx2, 4]] - y[self._kp[idx1:idx2, 5]]) zk = .5 * (z[self._kp[idx1:idx2, 6]] + z[self._kp[idx1:idx2, 7]] - z[self._kp[idx1:idx2, 4]] - z[self._kp[idx1:idx2, 5]]) self._sx[idx1:idx2, 0] = (yj * zk) - (zj * yk) self._sy[idx1:idx2, 0] = (zj * xk) - (xj * zk) self._sz[idx1:idx2, 0] = (xj * yk) - (yj * xk) self._sx[idx1:idx2, 1] = (yk * zi) - (zk * yi) self._sy[idx1:idx2, 1] = (zk * xi) - (xk * zi) self._sz[idx1:idx2, 1] = (xk * yi) - (yk * xi) self._sx[idx1:idx2, 2] = (yi * zj) - (zi * yj) self._sy[idx1:idx2, 2] = (zi * xj) - (xi * zj) self._sz[idx1:idx2, 2] = (xi * yj) - (yi * xj) if g3d_world.options.dim_mode is DIMMode.G2D_AXISYMM: r = 0.25 * (y[self._kp[idx1:idx2, 4]] + y[self._kp[idx1:idx2, 5]] + y[self._kp[idx1:idx2, 6]] + y[self._kp[idx1:idx2, 7]]) self._sx[idx1:idx2, 0] = r * self._sx[idx1:idx2, 0] self._sy[idx1:idx2, 0] = r * self._sy[idx1:idx2, 0] self._sz[idx1:idx2, 0] = r * self._sz[idx1:idx2, 0] self._sx[idx1:idx2, 1] = r * self._sx[idx1:idx2, 1] self._sy[idx1:idx2, 1] = r * self._sy[idx1:idx2, 1] self._sz[idx1:idx2, 1] = r * self._sz[idx1:idx2, 1] self._sx[idx1:idx2, 2] = r * self._sx[idx1:idx2, 2] self._sy[idx1:idx2, 2] = r * self._sy[idx1:idx2, 2] self._sz[idx1:idx2, 2] = r * self._sz[idx1:idx2, 2] self._si[idx1:idx2, 0] = self._sx[idx1:idx2, 0] self._si[idx1:idx2, 1] = self._sy[idx1:idx2, 0] self._si[idx1:idx2, 2] = self._sz[idx1:idx2, 0] self._voli[idx1:idx2] = ( 1.0 / (self._si[idx1:idx2, 0] * xi + self._si[idx1:idx2, 1] * yi + self._si[idx1:idx2, 2] * zi) )
[docs] def update_symmetry_ghost_nodes(self, x: ndarray, y: ndarray, z: ndarray) -> None: """Update geometric representation of symmetry plane ghost nodes (mirror nodes in symmetry plane) Parameters ---------- x: ndarray : x-coordinate vector y: ndarray : y-coordinate vector z: ndarray : z-coordinate vector """ # update ghost node coordinates for symmetry faces delta = np.zeros(3) for i_face in range(int(self._size / 2), self._size): for ip in range(4): delta[0] = x[self._kp[i_face, ip]] - x[self._kp[i_face, ip + 4]] delta[1] = y[self._kp[i_face, ip]] - y[self._kp[i_face, ip + 4]] delta[2] = z[self._kp[i_face, ip]] - z[self._kp[i_face, ip + 4]] dd = (delta[0] * self._s[i_face, 0] + delta[1] * self._s[i_face, 1] + delta[2] * self._s[i_face, 2]) / self._sl[i_face] for i in range(3): delta[i] -= 2. * dd * self._s[i_face, i] / self._sl[i_face] x[self._kp[i_face, ip + 8]] = x[self._kp[i_face, ip + 4]] + delta[0] y[self._kp[i_face, ip + 8]] = y[self._kp[i_face, ip + 4]] + delta[0] z[self._kp[i_face, ip + 8]] = z[self._kp[i_face, ip + 4]] + delta[0]
[docs] def update_wall_diff_metrics(self, x: ndarray, y: ndarray, z: ndarray) -> None: """Update wall face diffusive flux metrics Parameters ---------- x: ndarray : x-coordinate vector y: ndarray : y-coordinate vector z: ndarray : z-coordinate vector """ g3d_world = G3DWorld() idx1 = int(self._size / 2) idx2 = self._size xi = .25 * (x[self._kp[idx1:idx2, 4]] + x[self._kp[idx1:idx2, 5]] + x[self._kp[idx1:idx2, 6]] + x[self._kp[idx1:idx2, 7]] - x[self._kp[idx1:idx2, 0]] - x[self._kp[idx1:idx2, 1]] - x[self._kp[idx1:idx2, 2]] - x[self._kp[idx1:idx2, 3]]) yi = .25 * (y[self._kp[idx1:idx2, 4]] + y[self._kp[idx1:idx2, 5]] + y[self._kp[idx1:idx2, 6]] + y[self._kp[idx1:idx2, 7]] - y[self._kp[idx1:idx2, 0]] - y[self._kp[idx1:idx2, 1]] - y[self._kp[idx1:idx2, 2]] - y[self._kp[idx1:idx2, 3]]) zi = .25 * (z[self._kp[idx1:idx2, 4]] + z[self._kp[idx1:idx2, 5]] + z[self._kp[idx1:idx2, 6]] + z[self._kp[idx1:idx2, 7]] - z[self._kp[idx1:idx2, 0]] - z[self._kp[idx1:idx2, 1]] - z[self._kp[idx1:idx2, 2]] - z[self._kp[idx1:idx2, 3]]) xj = .5 * (x[self._kp[idx1:idx2, 5]] + x[self._kp[idx1:idx2, 7]] - x[self._kp[idx1:idx2, 4]] - x[self._kp[idx1:idx2, 6]]) yj = .5 * (y[self._kp[idx1:idx2, 5]] + y[self._kp[idx1:idx2, 7]] - y[self._kp[idx1:idx2, 4]] - y[self._kp[idx1:idx2, 6]]) zj = .5 * (z[self._kp[idx1:idx2, 5]] + z[self._kp[idx1:idx2, 7]] - z[self._kp[idx1:idx2, 4]] - z[self._kp[idx1:idx2, 6]]) xk = .5 * (x[self._kp[idx1:idx2, 6]] + x[self._kp[idx1:idx2, 7]] - x[self._kp[idx1:idx2, 4]] - x[self._kp[idx1:idx2, 5]]) yk = .5 * (y[self._kp[idx1:idx2, 6]] + y[self._kp[idx1:idx2, 7]] - y[self._kp[idx1:idx2, 4]] - y[self._kp[idx1:idx2, 5]]) zk = .5 * (z[self._kp[idx1:idx2, 6]] + z[self._kp[idx1:idx2, 7]] - z[self._kp[idx1:idx2, 4]] - z[self._kp[idx1:idx2, 5]]) self._sx[idx1:idx2, 0] = (yj * zk) - (zj * yk) self._sy[idx1:idx2, 0] = (zj * xk) - (xj * zk) self._sz[idx1:idx2, 0] = (xj * yk) - (yj * xk) self._sx[idx1:idx2, 1] = (yk * zi) - (zk * yi) self._sy[idx1:idx2, 1] = (zk * xi) - (xk * zi) self._sz[idx1:idx2, 1] = (xk * yi) - (yk * xi) self._sx[idx1:idx2, 2] = (yi * zj) - (zi * yj) self._sy[idx1:idx2, 2] = (zi * xj) - (xi * zj) self._sz[idx1:idx2, 2] = (xi * yj) - (yi * xj) if g3d_world.options.dim_mode is DIMMode.G2D_AXISYMM: r = 0.25 * (y[self._kp[idx1:idx2, 4]] + y[self._kp[idx1:idx2, 5]] + y[self._kp[idx1:idx2, 6]] + y[self._kp[idx1:idx2, 7]]) self._sx[idx1:idx2, 0] = r * self._sx[idx1:idx2, 0] self._sy[idx1:idx2, 0] = r * self._sy[idx1:idx2, 0] self._sz[idx1:idx2, 0] = r * self._sz[idx1:idx2, 0] self._sx[idx1:idx2, 1] = r * self._sx[idx1:idx2, 1] self._sy[idx1:idx2, 1] = r * self._sy[idx1:idx2, 1] self._sz[idx1:idx2, 1] = r * self._sz[idx1:idx2, 1] self._sx[idx1:idx2, 2] = r * self._sx[idx1:idx2, 2] self._sy[idx1:idx2, 2] = r * self._sy[idx1:idx2, 2] self._sz[idx1:idx2, 2] = r * self._sz[idx1:idx2, 2] self._si[idx1:idx2, 0] = self._sx[idx1:idx2, 0] self._si[idx1:idx2, 1] = self._sy[idx1:idx2, 0] self._si[idx1:idx2, 2] = self._sz[idx1:idx2, 0] self._voli[idx1:idx2] = ( 1.0 / (self._si[idx1:idx2, 0] * xi + self._si[idx1:idx2, 1] * yi + self._si[idx1:idx2, 2] * zi) ) # calculate wall normal coordinate for first cell self._y_norm = np.zeros(self._size) xc = 0.125 * (x[self._kp[idx1:idx2, 0]] + x[self._kp[idx1:idx2, 1]] + x[self._kp[idx1:idx2, 2]] + x[self._kp[idx1:idx2, 3]] + x[self._kp[idx1:idx2, 4]] + x[self._kp[idx1:idx2, 5]] + x[self._kp[idx1:idx2, 6]] + x[self._kp[idx1:idx2, 7]]) xc -= 0.25 * (x[self._kp[idx1:idx2, 4]] + x[self._kp[idx1:idx2, 5]] + x[self._kp[idx1:idx2, 6]] + x[self._kp[idx1:idx2, 7]]) yc = 0.125 * (y[self._kp[idx1:idx2, 0]] + y[self._kp[idx1:idx2, 1]] + y[self._kp[idx1:idx2, 2]] + y[self._kp[idx1:idx2, 3]] + y[self._kp[idx1:idx2, 4]] + y[self._kp[idx1:idx2, 5]] + y[self._kp[idx1:idx2, 6]] + y[self._kp[idx1:idx2, 7]]) yc -= 0.25 * (y[self._kp[idx1:idx2, 4]] + y[self._kp[idx1:idx2, 5]] + y[self._kp[idx1:idx2, 6]] + y[self._kp[idx1:idx2, 7]]) zc = 0.125 * (z[self._kp[idx1:idx2, 0]] + z[self._kp[idx1:idx2, 1]] + z[self._kp[idx1:idx2, 2]] + z[self._kp[idx1:idx2, 3]] + z[self._kp[idx1:idx2, 4]] + z[self._kp[idx1:idx2, 5]] + z[self._kp[idx1:idx2, 6]] + z[self._kp[idx1:idx2, 7]]) zc -= 0.25 * (z[self._kp[idx1:idx2, 4]] + z[self._kp[idx1:idx2, 5]] + z[self._kp[idx1:idx2, 6]] + z[self._kp[idx1:idx2, 7]]) self._y_norm[idx1:idx2] = -(xc * self._s[idx1:idx2, 0] + yc * self._s[idx1:idx2, 1] + zc * self._s[idx1:idx2, 2]) / self._sl[idx1:idx2]
[docs] def check_metrics(self, x: ndarray, y: ndarray, z: ndarray) -> None: """Check flux molecule metrics data Parameters ---------- x: ndarray : x-coordinate vector y: ndarray : y-coordinate vector z: ndarray : z-coordinate vector """ idx1 = 0 idx2 = self._size x[self._kc[idx1:idx2, 1]] -= self._s[idx1:idx2, 0] y[self._kc[idx1:idx2, 1]] -= self._s[idx1:idx2, 1] z[self._kc[idx1:idx2, 1]] -= self._s[idx1:idx2, 2] x[self._kc[idx1:idx2, 2]] += self._s[idx1:idx2, 0] y[self._kc[idx1:idx2, 2]] += self._s[idx1:idx2, 1] z[self._kc[idx1:idx2, 2]] += self._s[idx1:idx2, 2]
[docs] def check_cell_metrics(self, ic: int, check_sum: ndarray): """Check cell metrics data Parameters ---------- ic: int : cell index check_sum: ndarray : accumulated check sum """ for i_face in range(self._size): if self._kc[i_face, 1] == ic: print( ' i_face %d: [%e,%e,%e]' % (i_face, -self._s[i_face, 0], -self._s[i_face, 1], -self._s[i_face, 2])) for i in range(3): check_sum[i] -= self._s[i_face, i] elif self._kc[i_face, 2] == ic: print(' i_face %d: [%e,%e,%e]' % (i_face, self._s[i_face, 0], self._s[i_face, 1], self._s[i_face, 2])) for i in range(3): check_sum[i] += self._s[i_face, i]
[docs] def print_data(self, f: TextIO = None) -> None: """Prints cell pointers, node pointers, and face metrics to file (or stdout) Parameters ---------- f: TextIO : ascii file handle (Default value = None) """ if f is not None: for i in range(self._size): f.write('face idx: %d\n' % i) f.write('kc: %s\n' % str(self._kc[i, :])) f.write('kp: %s\n' % str(self._kp[i, :])) f.write('s: %s\n' % str(self._s[i, :])) else: for i in range(self._size): print('face idx: %d' % i) print(self._kc[i, :]) print(self._kp[i, :]) print(self._s[i, :])
[docs] class FMPArray: """Definition of class FMPArray: flux molecule placeholder container""" def __init__(self): self.__size = 0 self.__FMPs = [] @property def size(self) -> int: """Storage size Returns ------- int size """ return self.__size @property def FMPs(self) -> list: """Flux molecule placeholder list Returns ------- list list of allocated flux molecule placeholders """ return self.__FMPs
[docs] def add_FMP(self, **kwargs: Any) -> None: """Adds flux molecule to container Parameters ---------- **kwargs: Any : keyword-argument pairs will be forwarded to flux molecule placeholder (FMP) constructor see :func:'set_from_key_value' """ fmp = FMP(**kwargs) if len(fmp.tag) == 0: if fmp.type != FMPTypes.UNDEFINED: fmp.tag = fmp.type.name else: fmp.tag = 'FMP ' + str(self.__size) self.__FMPs.append(fmp) self.__size += 1
[docs] def allocate_FMPs(self, N: int = 0, idx: int = None) -> None: """Allocates flux molecule placeholders in container - all flux molecules placeholders or one specific Parameters ---------- N: int : flux molecule placeholder array length (Default value = 0) idx: int : flux molecule placeholder index listed in this container (Default value = None) """ if idx is None: for fmp in self.__FMPs: fmp.allocate(size=N) else: self.__FMPs[idx].allocate(size=N)
[docs] def deallocate_FMPs(self) -> None: """Deallocates listed flux molecule placeholders""" for i in range(self.__size): self.__FMPs[i] = FMP()
[docs] def get_FMPs(self, idx: int = None) -> Union[list, FMP]: """ Parameters ---------- idx : return: idx: int : (Default value = None) Returns ------- """ if idx is None: return self.__FMPs else: return self.__FMPs[idx]
[docs] def set_FMP_tag(self, idx: int, tag: str) -> None: """ Parameters ---------- idx : param tag: idx: int : tag: str : Returns ------- """ self.__FMPs[idx].tag = tag
[docs] def set_FMP_data(self, idx: int, face_idx: int, kp: int, kc: int, fctj: float, fctk: float) -> None: """ Parameters ---------- idx : param face_idx: kp : param kc: fctj : param fctk: idx: int : face_idx: int : kp: int : kc: int : fctj: float : fctk: float : Returns ------- """ self.__FMPs[idx].set_data(face_idx, kp, kc, fctj, fctk)
[docs] def get_max_FMP_size(self) -> int: """:return:""" FMP_size = 0 for tmp in self.__FMPs: FMP_size = max(FMP_size, tmp.size) return FMP_size
[docs] def update_FMP_metrics(self, x: ndarray, y: ndarray, z: ndarray) -> None: """ Parameters ---------- x : param y: z : x: ndarray : y: ndarray : z: ndarray : Returns ------- """ for tmp in self.__FMPs: tmp.update_metrics(x, y, z)
[docs] def update_FMP_diff_metrics(self, x: ndarray, y: ndarray, z: ndarray) -> None: """ Parameters ---------- x : param y: z : x: ndarray : y: ndarray : z: ndarray : Returns ------- """ for tmp in self.__FMPs: tmp.update_diff_metrics(x, y, z)
[docs] def check_FMP_metrics(self, x: ndarray, y: ndarray, z: ndarray, tag: str = 'ALL') -> None: """ Parameters ---------- x : param y: z : param tag: x: ndarray : y: ndarray : z: ndarray : tag: str : (Default value = 'ALL') Returns ------- """ for tmp in self.__FMPs: if tag == tmp.tag or tag == 'ALL': tmp.check_metrics(x, y, z)
[docs] def check_FMP_cell_metrics(self, ic: int, check_sum: Union[ndarray, list[float]]) -> None: """ Parameters ---------- ic : param check_sum: ic: int : check_sum: Union[ndarray : list[float]] : Returns ------- """ for tmp in self.__FMPs: print(' flux molecule tag: %s' % tmp.tag) tmp.check_cell_metrics(ic, check_sum)
[docs] def print_FMP_data(self, tag: str = 'ALL', f: TextIO = None) -> None: """ Parameters ---------- tag : param f: tag: str : (Default value = 'ALL') f: TextIO : (Default value = None) Returns ------- """ for tmp in self.__FMPs: if tag == tmp.tag or tag == 'ALL': tmp.print_data(f)