"""Velocity gradients - flow field data placeholder (VGradField class definition)"""
from typing import Any, Union, Tuple
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 GradientMode
from g3d.flow.placeholders import FlowDataPlaceHolder
from g3d.flow.vars import VGrad
from g3d.flow.placeholders import FMP
[docs]
class VGradField(FlowDataPlaceHolder):
"""Definition of class VGradField, extends class FlowDataPlaceHolder"""
def __init__(self, *args: Any, **kwargs: Any) -> None:
self.__s_vel = np.zeros(0)
self.__u_face = np.zeros(0)
self.__v_face = np.zeros(0)
self.__w_face = np.zeros(0)
super().__init__(*args, **kwargs)
@property
def dudx(self) -> ndarray:
"""Velocity gradient component
Returns
-------
ndarray
dudx array
"""
return self._dudx
@property
def dudy(self) -> ndarray:
"""Velocity gradient component
Returns
-------
ndarray
dudy array
"""
return self._dudy
@property
def dudz(self) -> ndarray:
"""Velocity gradient component
Returns
-------
ndarray
dudz array
"""
return self._dudz
@property
def dvdx(self) -> ndarray:
"""Velocity gradient component
Returns
-------
ndarray
dvdx array
"""
return self._dvdx
@property
def dvdy(self) -> ndarray:
"""Velocity gradient component
Returns
-------
ndarray
dvdy array
"""
return self._dvdy
@property
def dvdz(self) -> ndarray:
"""Velocity gradient component
Returns
-------
ndarray
dvdz array
"""
return self._dvdz
@property
def dwdx(self) -> ndarray:
"""Velocity gradient component
Returns
-------
ndarray
dwdx array
"""
return self._dwdx
@property
def dwdy(self) -> ndarray:
"""Velocity gradient component
Returns
-------
ndarray
dwdy array
"""
return self._dwdy
@property
def dwdz(self) -> ndarray:
"""Velocity gradient component
Returns
-------
ndarray
dwdz array
"""
return self._dwdz
def _set_default(self) -> None:
super()._set_default()
self._tag = 'velocity gradients'
def _define_variables(self) -> None:
super()._define_variables()
self._variables['dudx'] = {}
self._variables['dudx']['longname'] = 'dudx'
self._variables['dudx']['dimension'] = '1/s'
self._variables['dudy'] = {}
self._variables['dudy']['longname'] = 'dudy'
self._variables['dudy']['dimension'] = '1/s'
self._variables['dudz'] = {}
self._variables['dudz']['longname'] = 'dudz'
self._variables['dudz']['dimension'] = '1/s'
self._variables['dvdx'] = {}
self._variables['dvdx']['longname'] = 'dvdx'
self._variables['dvdx']['dimension'] = '1/s'
self._variables['dvdy'] = {}
self._variables['dvdy']['longname'] = 'dvdy'
self._variables['dvdy']['dimension'] = '1/s'
self._variables['dvdz'] = {}
self._variables['dvdz']['longname'] = 'dvdz'
self._variables['dvdz']['dimension'] = '1/s'
self._variables['dwdx'] = {}
self._variables['dwdx']['longname'] = 'dwdx'
self._variables['dwdx']['dimension'] = '1/s'
self._variables['dwdy'] = {}
self._variables['dwdy']['longname'] = 'dwdy'
self._variables['dwdy']['dimension'] = '1/s'
self._variables['dwdz'] = {}
self._variables['dwdz']['longname'] = 'dwdz'
self._variables['dwdz']['dimension'] = '1/s'
def _allocate_placeholders(self) -> None:
super()._allocate_placeholders()
self._dudx = np.zeros(self._size)
self._dudy = np.zeros(self._size)
self._dudz = np.zeros(self._size)
self._dvdx = np.zeros(self._size)
self._dvdy = np.zeros(self._size)
self._dvdz = np.zeros(self._size)
self._dwdx = np.zeros(self._size)
self._dwdy = np.zeros(self._size)
self._dwdz = np.zeros(self._size)
self._variables['dudx']['ref'] = self._dudx
self._variables['dudy']['ref'] = self._dudy
self._variables['dudz']['ref'] = self._dudz
self._variables['dvdx']['ref'] = self._dvdx
self._variables['dvdy']['ref'] = self._dvdy
self._variables['dvdz']['ref'] = self._dvdz
self._variables['dwdx']['ref'] = self._dwdx
self._variables['dwdy']['ref'] = self._dwdy
self._variables['dwdz']['ref'] = self._dwdz
[docs]
def allocate_flux_molecule_placeholders(self, N: int = 0) -> None:
"""Allocates flux molecule data placeholders
Parameters
----------
N: int :
number of faces (Default value = 0)
"""
self.__s_vel = np.zeros(N)
self.__u_face = np.zeros(N)
self.__v_face = np.zeros(N)
self.__w_face = np.zeros(N)
[docs]
def set_values(self, dd: ndarray, idx: int = None) -> None:
"""Sets array values for all cells or cell with specified cell index to a set of initial values or data from
provided array
Parameters
----------
dd: ndarray :
velocity gradient array (3x3)
idx: int :
cell index (Default value = None)
"""
if idx is None:
idx1, idx2 = self.get_range()
self._dudx[idx1:idx2] = dd[0][0]
self._dudy[idx1:idx2] = dd[0][1]
self._dudz[idx1:idx2] = dd[0][2]
self._dvdx[idx1:idx2] = dd[1][0]
self._dvdy[idx1:idx2] = dd[1][1]
self._dvdz[idx1:idx2] = dd[1][2]
self._dwdx[idx1:idx2] = dd[2][0]
self._dwdy[idx1:idx2] = dd[2][1]
self._dwdz[idx1:idx2] = dd[2][2]
else:
self._dudx[idx] = dd[0][0]
self._dudy[idx] = dd[0][1]
self._dudz[idx] = dd[0][2]
self._dvdx[idx] = dd[1][0]
self._dvdy[idx] = dd[1][1]
self._dvdz[idx] = dd[1][2]
self._dwdx[idx] = dd[2][0]
self._dwdy[idx] = dd[2][1]
self._dwdz[idx] = dd[2][2]
[docs]
def get_VGrad(self, idx: int) -> ndarray:
"""Gets velocity gradients for specified cell index
Parameters
----------
idx: int :
cell index
"""
dd = np.zeros((3, 3))
dd[0][0] = self._dudx[idx]
dd[0][1] = self._dudy[idx]
dd[0][2] = self._dudz[idx]
dd[1][0] = self._dvdx[idx]
dd[1][1] = self._dvdy[idx]
dd[1][2] = self._dvdz[idx]
dd[2][0] = self._dwdx[idx]
dd[2][1] = self._dwdy[idx]
dd[2][2] = self._dwdz[idx]
return dd
[docs]
def set_from_VGrad(self, vgrad: VGrad) -> None:
"""Sets data from prototype VGrad object
Parameters
----------
vgrad: VGrad :
instance of velocity gradient VGrad object
"""
idx1, idx2 = self.get_range()
self._dudx[idx1:idx2] = vgrad.dudx
self._dudy[idx1:idx2] = vgrad.dudy
self._dudz[idx1:idx2] = vgrad.dudz
self._dvdx[idx1:idx2] = vgrad.dvdx
self._dvdy[idx1:idx2] = vgrad.dvdy
self._dvdz[idx1:idx2] = vgrad.dvdz
self._dwdx[idx1:idx2] = vgrad.dwdx
self._dwdy[idx1:idx2] = vgrad.dwdy
self._dwdz[idx1:idx2] = vgrad.dwdz
[docs]
def set_from_arrays(self,
dudx: ndarray, dudy: ndarray, dudz: ndarray,
dvdx: ndarray, dvdy: ndarray, dvdz: ndarray,
dwdx: ndarray, dwdy: ndarray, dwdz: ndarray) -> None:
"""Sets velocity gradient values from provided arrays
Parameters
----------
dudx: ndarray :
dudx array
dudy: ndarray :
dudy array
dudz: ndarray :
dudz array
dvdx: ndarray :
dvdx array
dvdy: ndarray :
dvdy array
dvdz: ndarray :
dvdz array
dwdx: ndarray :
dwdx array
dwdy: ndarray :
dwdy array
dwdz: ndarray :
dwdz array
"""
idx1, idx2 = self.get_range()
self._dudx[idx1:idx2] = dudx[idx1:idx2]
self._dudy[idx1:idx2] = dudy[idx1:idx2]
self._dudz[idx1:idx2] = dudz[idx1:idx2]
self._dvdx[idx1:idx2] = dvdx[idx1:idx2]
self._dvdy[idx1:idx2] = dvdy[idx1:idx2]
self._dvdz[idx1:idx2] = dvdz[idx1:idx2]
self._dwdx[idx1:idx2] = dwdx[idx1:idx2]
self._dwdy[idx1:idx2] = dwdy[idx1:idx2]
self._dwdz[idx1:idx2] = dwdz[idx1:idx2]
[docs]
def get_arrays(self) -> Tuple[ndarray, ...]:
"""Gets velocity gradient arrays
Returns
-------
tuple
tuple of ndarray (dudx, dudy, dudz, dvdx, dvdy, dvdz, dwdx, dwdy, dwdz)
"""
idx1, idx2 = self.get_range()
return (
self._dudx[idx1:idx2],
self._dudy[idx1:idx2],
self._dudz[idx1:idx2],
self._dvdx[idx1:idx2],
self._dvdy[idx1:idx2],
self._dvdz[idx1:idx2],
self._dwdx[idx1:idx2],
self._dwdy[idx1:idx2],
self._dwdz[idx1:idx2])
[docs]
def get_arrays_with_ghosts(self) -> Tuple[ndarray, ...]:
"""Gets velocity gradient arrays including ghost values
Returns
-------
tuple
tuple of ndarray (dudx, dudy, dudz, dvdx, dvdy, dvdz, dwdx, dwdy, dwdz)
"""
return (
self._dudx,
self._dudy,
self._dudz,
self._dvdx,
self._dvdy,
self._dvdz,
self._dwdx,
self._dwdy,
self._dwdz)
[docs]
def set_from_gradient_field(self, v: 'VGradField') -> None:
"""Sets velocity gradient values from prototype VGradField object
Parameters
----------
v: VGradField :
prototype VGradField object
"""
dudx, dudy, dudz, dvdx, dvdy, dvdz, dwdx, dwdy, dwdz = v.get_arrays()
self.set_from_arrays(dudx, dudy, dudz, dvdx, dvdy, dvdz, dwdx, dwdy, dwdz)
[docs]
def get_divergence(self, idx: int) -> float:
"""Extracts the divergence of the velocity field for specified cell index
Parameters
----------
idx: int :
cell index
Returns
-------
float
divergence of velocity field
"""
return self._dudx[idx] + self._dvdy[idx] + self._dwdz[idx]
[docs]
def get_vorticity(self, idx: int) -> ndarray:
"""Extracts the vorticity vector for specified cell index
Parameters
----------
idx: int :
cell index
Returns
-------
ndarray
vorticity vector
"""
v = np.zeros(3)
v[0] = self._dwdy[idx] - self._dvdz[idx]
v[1] = self._dudz[idx] - self._dwdx[idx]
v[2] = self._dvdx[idx] - self._dudy[idx]
return v
[docs]
def get_vorticity_magnitude(self, idx: int) -> float:
"""Calculates the vorticity magnitude for specified cell index
Parameters
----------
idx: int :
cell index
Returns
-------
float
vorticity magnitude
"""
v = self.get_vorticity(idx)
return np.sqrt(sum(v * v))
[docs]
def get_SijSij(self, idx: int) -> float:
"""Gets strain rate tensor product for specified cell index
Parameters
----------
idx: int :
cell index
Returns
-------
float
SijSij
"""
return (self._dudx[idx] ** 2 + self._dvdy[idx] ** 2 + self._dwdz[idx] ** 2
+ 0.5 * ((self._dudy[idx] + self._dvdx[idx]) ** 2
+ (self._dudz[idx] + self._dwdx[idx]) ** 2
+ (self._dvdz[idx] + self._dwdy[idx]) ** 2))
def __get_face_velocities(self, u: ndarray, v: ndarray, w: ndarray, s: ndarray,
kc: Union[ndarray, list], idx1: int, idx2: int, MODE: Any = GradientMode.AVERAGE):
if type(MODE) is GradientMode:
if MODE is GradientMode.AVERAGE:
self.__u_face[idx1:idx2] = 0.5 * (u[kc[idx1:idx2, 1]] + u[kc[idx1:idx2, 2]])
self.__v_face[idx1:idx2] = 0.5 * (v[kc[idx1:idx2, 1]] + v[kc[idx1:idx2, 2]])
self.__w_face[idx1:idx2] = 0.5 * (w[kc[idx1:idx2, 1]] + w[kc[idx1:idx2, 2]])
return
if MODE is GradientMode.BOUNDARY_MIRROR:
self.__s_vel[idx1:idx2] = (s[idx1:idx2, 0] * u[kc[idx1:idx2, 1]] +
s[idx1:idx2, 1] * v[kc[idx1:idx2, 1]] +
s[idx1:idx2, 2] * w[kc[idx1:idx2, 1]])
self.__u_face[idx1:idx2] = u[kc[idx1:idx2, 1]] - self.__s_vel[idx1:idx2] * s[idx1:idx2, 0]
self.__v_face[idx1:idx2] = v[kc[idx1:idx2, 1]] - self.__s_vel[idx1:idx2] * s[idx1:idx2, 1]
self.__w_face[idx1:idx2] = w[kc[idx1:idx2, 1]] - self.__s_vel[idx1:idx2] * s[idx1:idx2, 2]
return
if MODE is GradientMode.BOUNDARY_EXTRAPOLATE:
self.__u_face[idx1:idx2] = 1.5 * u[kc[idx1:idx2, 1]] - 0.5 * u[kc[idx1:idx2, 0]]
self.__v_face[idx1:idx2] = 1.5 * v[kc[idx1:idx2, 1]] - 0.5 * v[kc[idx1:idx2, 0]]
self.__w_face[idx1:idx2] = 1.5 * w[kc[idx1:idx2, 1]] - 0.5 * w[kc[idx1:idx2, 0]]
return
[docs]
def add_gradients(self, u: ndarray, v: ndarray, w: ndarray,
fmp: FMP, StartIndex: int = 0, n_faces: int = 0, MODE: Any = GradientMode.AVERAGE) -> None:
"""Add face contribution to velocity gradient field
Parameters
----------
u : ndarray :
x-velocity vector
v : ndarray :
y-velocity vector
w : ndarray :
z-velocity vector
fmp : FMP :
flux molecule pointer placeholder
StartIndex : int :
first index (Default value = 0)
n_faces : int :
number of faces (Default value = 0)
MODE : GradientMode :
type of gradient calculation (Default value = GradientMode.AVERAGE)
"""
if type(MODE) is GradientMode:
if np.int32(n_faces) == 0:
n_faces = fmp.size - StartIndex
n_faces, idx1, idx2 = np.int32([n_faces, StartIndex, StartIndex + n_faces])
if n_faces == 0:
return
kp, kc = fmp.get_pointers()
s, sl = fmp.get_conv_metrics()
self.__get_face_velocities(u, v, w, s, kc, idx1, idx2, MODE)
self._dudx[kc[idx1:idx2, 1]] += self.__u_face[idx1:idx2] * s[idx1:idx2, 0]
self._dudy[kc[idx1:idx2, 1]] += self.__u_face[idx1:idx2] * s[idx1:idx2, 1]
self._dudz[kc[idx1:idx2, 1]] += self.__u_face[idx1:idx2] * s[idx1:idx2, 2]
self._dvdx[kc[idx1:idx2, 1]] += self.__v_face[idx1:idx2] * s[idx1:idx2, 0]
self._dvdy[kc[idx1:idx2, 1]] += self.__v_face[idx1:idx2] * s[idx1:idx2, 1]
self._dvdz[kc[idx1:idx2, 1]] += self.__v_face[idx1:idx2] * s[idx1:idx2, 2]
self._dwdx[kc[idx1:idx2, 1]] += self.__w_face[idx1:idx2] * s[idx1:idx2, 0]
self._dwdy[kc[idx1:idx2, 1]] += self.__w_face[idx1:idx2] * s[idx1:idx2, 1]
self._dwdz[kc[idx1:idx2, 1]] += self.__w_face[idx1:idx2] * s[idx1:idx2, 2]
self._dudx[kc[idx1:idx2, 2]] -= self.__u_face[idx1:idx2] * s[idx1:idx2, 0]
self._dudy[kc[idx1:idx2, 2]] -= self.__u_face[idx1:idx2] * s[idx1:idx2, 1]
self._dudz[kc[idx1:idx2, 2]] -= self.__u_face[idx1:idx2] * s[idx1:idx2, 2]
self._dvdx[kc[idx1:idx2, 2]] -= self.__v_face[idx1:idx2] * s[idx1:idx2, 0]
self._dvdy[kc[idx1:idx2, 2]] -= self.__v_face[idx1:idx2] * s[idx1:idx2, 1]
self._dvdz[kc[idx1:idx2, 2]] -= self.__v_face[idx1:idx2] * s[idx1:idx2, 2]
self._dwdx[kc[idx1:idx2, 2]] -= self.__w_face[idx1:idx2] * s[idx1:idx2, 0]
self._dwdy[kc[idx1:idx2, 2]] -= self.__w_face[idx1:idx2] * s[idx1:idx2, 1]
self._dwdz[kc[idx1:idx2, 2]] -= self.__w_face[idx1:idx2] * s[idx1:idx2, 2]