"""Conservative variables - flow field data placeholder (ConsField 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 G3DWorld
from g3d.defs import DIMMode
from g3d.flow.vars import Cons
from g3d.flow.placeholders import FlowDataPlaceHolder
from g3d.mesh.geo import Coordinates
[docs]
class ConsField(FlowDataPlaceHolder):
"""Definition of class ConsField, extends class FlowDataPlaceHolder: conservative flow variables container"""
def __init__(self, *args: Any, **kwargs: Any) -> None:
super().__init__(*args, **kwargs)
@property
def ro(self) -> ndarray:
"""Density [kg/m^3]
Returns
-------
ndarray
density array
"""
return self._ro
@property
def ru(self) -> ndarray:
"""X-momentum [kg/(m^2 s)]
Returns
-------
ndarray
x-momentum array
"""
return self._ru
@property
def rv(self) -> ndarray:
"""Y-momentum [kg/(m^2 s)]
Returns
-------
ndarray
y-momentum array
"""
return self._rv
@property
def rw(self) -> ndarray:
"""Z-momentum [kg/(m^2 s)]
Returns
-------
ndarray
z-momentum array
"""
return self._rw
@property
def et(self) -> ndarray:
"""Total energy [J/m^3]
Returns
-------
ndarray
total energy array
"""
return self._et
def _set_default(self) -> None:
super()._set_default()
self._tag = 'conservative variables'
def _define_variables(self) -> None:
super()._define_variables()
self._variables['ro'] = {}
self._variables['ro']['longname'] = 'density'
self._variables['ro']['dimension'] = 'kg/m^3'
self._variables['ru'] = {}
self._variables['ru']['longname'] = 'x-momentum'
self._variables['ru']['dimension'] = 'kg/(m^2 s)'
self._variables['rv'] = {}
self._variables['rv']['longname'] = 'y-momentum'
self._variables['rv']['dimension'] = 'kg/(m^2 s)'
self._variables['rw'] = {}
self._variables['rw']['longname'] = 'z-momentum'
self._variables['rw']['dimension'] = 'kg/(m^2 s)'
self._variables['et'] = {}
self._variables['et']['longname'] = 'energy'
self._variables['et']['dimension'] = 'J kg/m^3'
self.__define_sigma_placeholder()
g3d_world = G3DWorld()
g3d_world.sizes.n_var = len(self._variables.keys())
def __define_sigma_placeholder(self) -> None:
g3d_world = G3DWorld()
if g3d_world.options.dim_mode is DIMMode.Q3D:
if 'sigma' not in self._variables:
self._variables['sigma'] = {}
self._variables['sigma']['longname'] = 'stream tube source term'
self._variables['sigma']['dimension'] = 'N/m^3'
def _allocate_placeholders(self) -> None:
self.__define_sigma_placeholder()
super()._allocate_placeholders()
self._ro = np.zeros(self._size)
self._ru = np.zeros(self._size)
self._rv = np.zeros(self._size)
self._rw = np.zeros(self._size)
self._et = np.zeros(self._size)
self._variables['ro']['ref'] = self._ro
self._variables['ru']['ref'] = self._ru
self._variables['rv']['ref'] = self._rv
self._variables['rw']['ref'] = self._rw
self._variables['et']['ref'] = self._et
if G3DWorld().options.dim_mode is DIMMode.Q3D:
self._sigma = np.zeros(self._size)
self._variables['sigma']['ref'] = self._sigma
[docs]
def set_values(self,
ro: Union[float, ndarray],
ru: Union[float, ndarray],
rv: Union[float, ndarray],
rw: Union[float, ndarray],
et: Union[float, 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 arrays
Parameters
----------
ro : float or ndarray :
density value or array of values
ru : float or ndarray :
x-momentum value or array of values
rv : float or ndarray :
y-momentum value or array of values
rw : float or ndarray :
z-momentum value or array of values
et : float or ndarray :
total energy value or array of values
idx : int :
cell index (Default value = None)
"""
if idx is None:
idx1, idx2 = self.get_range()
self._ro[idx1:idx2] = ro
self._ru[idx1:idx2] = ru
self._rv[idx1:idx2] = rv
self._rw[idx1:idx2] = rw
self._et[idx1:idx2] = et
else:
self._ro[idx] = ro
self._ru[idx] = ru
self._rv[idx] = rv
self._rw[idx] = rw
self._et[idx] = et
[docs]
def get_Cons(self, idx: int) -> Cons:
"""Extracts an instance of conservative variable object for specified cell index
Parameters
----------
idx : int :
cell index
Returns
-------
Cons
conservative variable object
"""
q = Cons()
q.ro = self._ro[idx]
q.ru = self._ru[idx]
q.rv = self._rv[idx]
q.rw = self._rw[idx]
q.et = self._et[idx]
return q
[docs]
def get_by_index(self, idx: int) -> Tuple[float, ...]:
"""Gets tuple of conservative variable values for cell with specified index
Parameters
----------
idx : int :
cell index
Returns
-------
tuple
conservative variable values (ro, ru, rv, rw, et)
"""
return self._ro[idx], self._ru[idx], self._rv[idx], self._rw[idx], self._et[idx]
[docs]
def set_momentum_vector(self, idx: int, r_vel: Union[ndarray, list[float], Tuple[float, ...]]) -> None:
"""Set momentum vector for cell with specified index
Parameters
----------
idx : int :
cell index
r_vel : ndarray, list, or tuple :
momentum vector (ru, rv, rw)
"""
self._ru[idx] = r_vel[0]
self._rv[idx] = r_vel[1]
self._rw[idx] = r_vel[2]
[docs]
def get_momentum_vector(self, idx: int) -> ndarray:
"""Get momentum vector for cell with specified index
Parameters
----------
idx : int :
cell index
Returns
-------
ndarray
momentum vector (ru, rv, rw)
"""
return np.array([self._ru[idx], self._rv[idx], self._rw[idx]])
[docs]
def set_from_arrays(self, ro: ndarray, ru: ndarray, rv: ndarray, rw: ndarray, et: ndarray) -> None:
"""Set data from provided arrays
Parameters
----------
ro : ndarray :
density data
ru : ndarray :
x-momentum data
rv : ndarray :
y-momentum data
rw : ndarray :
z-momentum data
et : ndarray :
total energy data
"""
idx1, idx2 = self.get_range()
self._ro[idx1:idx2] = ro[idx1:idx2]
self._ru[idx1:idx2] = ru[idx1:idx2]
self._rv[idx1:idx2] = rv[idx1:idx2]
self._rw[idx1:idx2] = rw[idx1:idx2]
self._et[idx1:idx2] = et[idx1:idx2]
[docs]
def get_arrays(self) -> Tuple[ndarray, ...]:
"""Gets conservative flow data arrays
Returns
-------
tuple
data arrays (ro, ru, rv, rw, et)
"""
idx1, idx2 = self.get_range()
return (
self._ro[idx1:idx2],
self._ru[idx1:idx2],
self._rv[idx1:idx2],
self._rw[idx1:idx2],
self._et[idx1:idx2])
[docs]
def get_arrays_with_ghosts(self) -> Tuple[ndarray, ...]:
"""Gets conservative flow data arrays including ghost cell values
Returns
-------
tuple
data arrays (ro, ru, rv, rw, et)
"""
return (
self._ro,
self._ru,
self._rv,
self._rw,
self._et)
[docs]
def set_from_Cons(self, c: Cons) -> None:
"""Set array values from provided conservative variable object
Parameters
----------
c : Cons :
conservative variable object
"""
idx1, idx2 = self.get_range()
self._ro[idx1:idx2] = c.ro
self._ru[idx1:idx2] = c.ru
self._rv[idx1:idx2] = c.rv
self._rw[idx1:idx2] = c.rw
self._et[idx1:idx2] = c.et
[docs]
def set_by_index_from_Cons(self, idx: int, c: Cons) -> None:
"""Set array values for cell with specified cell index from provided conservative variable object
Parameters
----------
idx : int :
cell index
c : Cons :
conservative variable object
"""
self._ro[idx] = c.ro
self._ru[idx] = c.ru
self._rv[idx] = c.rv
self._rw[idx] = c.rw
self._et[idx] = c.et
[docs]
def set_from_cons_field(self, c: 'ConsField') -> None:
"""Copy data from provided conservative variables placeholder object
Parameters
----------
c : ConsField :
conservative variables container
"""
ro, ru, rv, rw, et = c.get_arrays()
self.set_from_arrays(ro, ru, rv, rw, et)
g3d_world = G3DWorld()
if g3d_world.options.dim_mode is DIMMode.Q3D:
self.set_from_array(c.get_array('sigma'), 'sigma')
# -- OLD STUFF --#
[docs]
def CellToNode(self, c: 'ConsField') -> None:
"""Convert cell values to node values
Parameters
----------
c : ConsField :
conservative variables container
"""
c_first, c_last = c.get_range()
c_n_cells = c_last - c_first
c_n_nodes = c_n_cells + 1
self.setup(n_cells=c_n_nodes)
self.nullify()
for i in range(c_n_cells):
j = i + c_first
self._ro[i] += 0.5 * c.ro[j]
self._ro[i + 1] += 0.5 * c.ro[j]
self._ru[i] += 0.5 * c.ru[j]
self._ru[i + 1] += 0.5 * c.ru[j]
self._rv[i] += 0.5 * c.rv[j]
self._rv[i + 1] += 0.5 * c.rv[j]
self._rw[i] += 0.5 * c.rw[j]
self._rw[i + 1] += 0.5 * c.rw[j]
self._et[i] += 0.5 * c.et[j]
self._et[i + 1] += 0.5 * c.et[j]
self._ro[0] = 4.0 * self._ro[0] - self._ro[1]
self._ru[0] = 4.0 * self._ru[0] - self._ru[1]
self._rv[0] = 4.0 * self._rv[0] - self._rv[1]
self._rw[0] = 4.0 * self._rw[0] - self._rw[1]
self._et[0] = 4.0 * self._et[0] - self._et[1]
self._ro[self._size - 1] = 4.0 * self._ro[self._size - 1] - self._ro[self._size - 2]
self._ru[self._size - 1] = 4.0 * self._ru[self._size - 1] - self._ru[self._size - 2]
self._rv[self._size - 1] = 4.0 * self._rv[self._size - 1] - self._rv[self._size - 2]
self._rw[self._size - 1] = 4.0 * self._rw[self._size - 1] - self._rw[self._size - 2]
self._et[self._size - 1] = 4.0 * self._et[self._size - 1] - self._et[self._size - 2]
[docs]
def Interpolate(self, nodes: Coordinates, cells: Coordinates, node_cons: 'ConsField') -> None:
"""Interpolate cell-centered flow field data to node-centered data
Parameters
----------
nodes : Coordinates :
node coordinates
cells : Coordinates :
cell coordinates
node_cons : ConsField :
node stored conservative variables
"""
idx = 0
for i in range(cells.size):
xc = cells.X[i]
cell_found = False
while idx < (nodes.size - 1):
if nodes.X[idx] <= xc <= nodes.X[idx + 1]:
cell_found = True
break
else:
idx = idx + 1
if cell_found:
interpolate_factor = (xc - nodes.X[idx]) / (nodes.X[idx + 1] - nodes.X[idx])
self._ro[i] = node_cons.ro[idx] + (node_cons.ro[idx + 1] - node_cons.ro[idx]) * interpolate_factor
self._ru[i] = node_cons.ru[idx] + (node_cons.ru[idx + 1] - node_cons.ru[idx]) * interpolate_factor
self._rv[i] = node_cons.rv[idx] + (node_cons.rv[idx + 1] - node_cons.rv[idx]) * interpolate_factor
self._rw[i] = node_cons.rw[idx] + (node_cons.rw[idx + 1] - node_cons.rw[idx]) * interpolate_factor
self._et[i] = node_cons.et[idx] + (node_cons.et[idx + 1] - node_cons.et[idx]) * interpolate_factor
# else:
# console.log('interpolation error: cell '+i+' (x = '+xc+') not found');