"""I/O functionality - geometry and flow import/export (G3DIO class definition)"""
from typing import Any, TextIO, TYPE_CHECKING
import sys
import os
if TYPE_CHECKING:
from g3d.flow.domain import Domain
from g3d.flow.placeholders import ConsField, AuxvField, PostField, VGradField, FlowDataPlaceHolder
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
import matplotlib.pyplot as plt
from g3d.defs import G3DWorld
from g3d.defs import G3DEntity
from g3d.defs import DIMMode
from g3d.defs import assure_path_exists
from g3d.defs import clean_path
[docs]
class G3DIO(G3DEntity):
"""Definition of class G3DIO: I/O functionality - geometry and flow import/export"""
def __init__(self, *args: Any, **kwargs: Any) -> None:
self._id = [0, 1, -1, 0, 0, 0, 0]
self._jd = [0, 0, 0, 1, -1, 0, 0]
self._kd = [0, 0, 0, 0, 0, 1, -1]
self._export_name = 'g3d.xml'
super().__init__(*args, **kwargs)
def _set_default(self) -> None:
super()._set_default()
self._tag = 'g3d_io'
self.__name_tags = ['name',
'export_name',
'xml_name',
'sol_dir',
'export_dir',
'xml_dir',
'remove_sub_path',
'label',
'subdir',
'variable_name',
'variable_names']
self.__reset_names()
def __reset_names(self) -> None:
self.__names = {}
for x in self.__name_tags:
if x == 'variable_name':
self.__names[x] = 'var'
elif x == 'variable_names':
self.__names[x] = []
else:
self.__names[x] = ''
[docs]
def set_from_key_value(self, key: str, value: Any) -> bool:
"""Sets data from key-value pair input
Parameters
----------
key: str :
keyword
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 == 'export_name':
self._export_name = value
return True
return False
[docs]
@staticmethod
def get_solution(cons: ConsField, filename: str) -> None:
"""Reads flow field data (solver variables) from file
Parameters
----------
cons : ConsField :
conservative variable container
filename : str :
file name
"""
cons.import_data(filename)
def __get_names(self, **kwargs: Any) -> None:
g3d_world = G3DWorld()
self.__reset_names()
xml_export = False
for key, value in kwargs.items():
if key in self.__name_tags:
self.__names[key] = value
elif key == 'no_xml':
xml_export = False
elif key == 'export_xml':
xml_export = value
name = self.__names['name']
subdir = self.__names['subdir']
if name == '':
name = g3d_world.io.wd + '/' + subdir + '/' + g3d_world.io.jobname
name = clean_path(name)
assure_path_exists(name)
self.__names['name'] = name
self.__names['sol_dir'] = os.path.dirname(name)
self.__names['export_dir'] = self.__names['sol_dir']
if xml_export:
name = self.__names['xml_name']
if name == '':
name = g3d_world.io.wd + '/' + subdir + '/' + g3d_world.io.jobname
name = clean_path(name)
assure_path_exists(name)
self.__names['xml_name'] = name
self.__names['xml_dir'] = os.path.dirname(name)
xml_dir = self.__names['xml_dir']
sol_dir = self.__names['sol_dir']
if len(sol_dir) and len(xml_dir):
if xml_dir in sol_dir:
if sol_dir.index(xml_dir) == 0:
self.__names['remove_sub_path'] = xml_dir
else:
self.__names['xml_name'] = ''
[docs]
@staticmethod
def add_geo_data_item(ni: int, nj: int, nk: int,
filename: str,
f: TextIO,
pos: int = 0,
dim_mode: Any = DIMMode.G3D,
bo: str = 'little') -> None:
"""Add geometric data item to xdmf file
Parameters
----------
ni : int :
number of nodes in i-direction
nj : int :
number of nodes in j-direction
nk : int :
number of nodes in k-direction
filename : str :
file name
f : TextIO :
file handle
pos : int :
file position (Default value = 0)
dim_mode : DIMMode
dimension mode (Default value = DIMMode.G3D)
bo : str :
byte order 'little' or 'big' (Default value = 'little')
"""
if dim_mode == DIMMode.G3D or dim_mode == DIMMode.Q3D:
f.write(' <DataItem Dimensions=\"%d %d %d 3\" NumberType=\"Float\"' % (nk, nj, ni))
f.write(' Precision=\"8\" Format=\"Binary\" Endian=\"%s\" Seek=\"%d\">\n' % (bo, pos))
elif dim_mode == DIMMode.G2D or dim_mode == DIMMode.G2D_AXISYMM:
f.write(' <DataItem Dimensions=\"1 %d %d 2\" NumberType=\"Float\"' % (nj, ni))
f.write(' Precision=\"8\" Format=\"Binary\" Endian=\"%s\" Seek=\"%d\">\n' % (bo, pos))
f.write(' %s\n' % filename)
f.write(' </DataItem>\n')
[docs]
@staticmethod
def add_cell_data_item(ni: int, nj: int, nk: int,
filename: str,
f: TextIO,
pos: int = 0,
dim_mode: Any = DIMMode.G3D,
bo: str = 'little') -> None:
"""Add cell data item to xdmf file
Parameters
----------
ni : int :
number of nodes in i-direction
nj : int :
number of nodes in j-direction
nk : int :
number of nodes in k-direction
filename : str :
file name
f : TextIO :
file handle
pos : int :
file position (Default value = 0)
dim_mode : DIMMode :
dimension mode (Default value = DIMMode.G3D)
bo : str :
byte order 'little' or 'big' (Default value = 'little')
"""
if dim_mode == DIMMode.G3D or dim_mode == DIMMode.Q3D:
f.write(' <DataItem Dimensions=\"%d %d %d 1\" NumberType=\"Float\"' % (nk - 1, nj - 1, ni - 1))
f.write(' Precision=\"8\" Format=\"Binary\" Endian=\"%s\" Seek=\"%d\">\n' % (bo, pos))
elif dim_mode == DIMMode.G2D or dim_mode == DIMMode.G2D_AXISYMM:
f.write(' <DataItem Dimensions=\"%d %d\" NumberType=\"Float\"' % (nj - 1, ni - 1))
f.write(' Precision=\"8\" Format=\"Binary\" Endian=\"%s\" Seek=\"%d\">\n' % (bo, pos))
f.write(' %s\n' % filename)
f.write(' </DataItem>\n')
[docs]
@staticmethod
def add_geo_attribute(im: int, ni: int, nj: int, nk: int, f: TextIO, dim_mode: Any = DIMMode.G3D):
"""Adds geometric attribute to xdmf file
Parameters
----------
im : int :
block number
ni : int :
number of nodes in i-direction
nj : int :
number of nodes in j-direction
nk : int :
number of nodes in k-direction
f : TextIO :
file handle
dim_mode : DIMMode :
dimension mode (Default value = DIMMode.G3D)
"""
if dim_mode == DIMMode.G3D or dim_mode == DIMMode.Q3D:
f.write(' <Topology TopologyType=\"3DSMesh\" Dimensions=\"%d %d %d\"/>\n' % (nk, nj, ni))
f.write(' <Geometry GeometryType=\"XYZ\">\n')
elif dim_mode == DIMMode.G2D or dim_mode == DIMMode.G2D_AXISYMM:
f.write(' <Topology TopologyType=\"2DSMesh\" Dimensions=\"%d %d\"/>\n' % (nj, ni))
f.write(' <Geometry GeometryType=\"XY\">\n')
f.write(' <DataItem Reference=\"/Xdmf/DataItem[%d]/DataItem[1]\" />\n' % (im + 1))
f.write(' </Geometry>\n')
[docs]
@staticmethod
def add_cell_attribute(variable: str, im: int, f: TextIO, item_counter: int = 2):
"""Adds cell attribute (flow data) to xdmf file
Parameters
----------
variable : str :
variable name
im : int :
block number
f : TextIO :
file handle
item_counter : int :
accumulated data-item count (Default value = 2)
"""
f.write(' <Attribute Name=\"%s\" Center=\"Cell\">\n' % variable)
f.write(' <DataItem Reference=\"/Xdmf/DataItem[%d]/DataItem[%d]\" />\n' % (im + 1, item_counter))
f.write(' </Attribute>\n')
[docs]
def export_flow(self, dom: 'Domain', cons: ConsField, auxv: AuxvField, post: PostField, **kwargs: Any) -> None:
"""Exports flow data to file
Parameters
----------
dom : Domain :
flow domain
cons : ConsField :
instance of conservative variables
auxv : AuxvField :
instance of primitive variables
post : PostField :
instance of postprocessing variables
**kwargs : Any :
keyword-value pairs
valid keyword: 'name', 'export_name', 'xml_name', 'sol_dir', 'export_dir', 'xml_dir', 'remove_sub_path',
'label', 'subdir', 'variable_name', 'variable_names', 'no_xml', 'export_xml'
"""
g3d_world = G3DWorld()
self.__get_names(**kwargs, export_xml=True)
name = self.__names['name']
xml_name = self.__names['xml_name']
remove_sub_path = self.__names['remove_sub_path']
mesh = dom.mesh
msh = xml_name + '.geo'
if not os.path.isfile(msh):
mesh.export(filename=xml_name)
auxv_variable_list = ['u', 'v', 'w', 'p', 't']
c_variables = cons.export(name)
a_variables = auxv.export(name)
p_variables = post.export(name)
if len(remove_sub_path) != 0:
msh = msh.replace(remove_sub_path, '').strip('/')
for var in c_variables.keys():
c_variables[var]['filename'] = c_variables[var]['filename'].replace(remove_sub_path, '').strip('/')
for var in a_variables.keys():
a_variables[var]['filename'] = a_variables[var]['filename'].replace(remove_sub_path, '').strip('/')
for var in p_variables.keys():
p_variables[var]['filename'] = p_variables[var]['filename'].replace(remove_sub_path, '').strip('/')
if g3d_world.options.dim_mode.value > DIMMode.Q1D.value:
nb = mesh.n_blocks
bo = sys.byteorder
xmf = xml_name + '.xmf'
xmf = clean_path(xmf)
print('generating xml meta data: %s' % xmf)
f = open(xmf, 'w')
self.add_xdmf_header(f)
node_pos = 0
cell_pos = 0
for im in range(nb):
ni, nj, nk = mesh.blocks[im].get_block_sizes()
f.write(' <DataItem Name=\"Collection %d\" ItemType=\"Collection\">\n' % (im + 1))
self.add_geo_data_item(ni, nj, nk, msh, f, node_pos, g3d_world.options.dim_mode, bo)
self.add_cell_data_item(ni, nj, nk, c_variables['ro']['filename'], f, cell_pos,
g3d_world.options.dim_mode, bo)
for var in auxv_variable_list:
self.add_cell_data_item(ni, nj, nk, a_variables[var]['filename'], f,
cell_pos, g3d_world.options.dim_mode, bo)
for var in p_variables.keys():
self.add_cell_data_item(ni, nj, nk, p_variables[var]['filename'], f,
cell_pos, g3d_world.options.dim_mode, bo)
f.write(' </DataItem>\n')
if g3d_world.options.dim_mode == DIMMode.G3D or g3d_world.options.dim_mode == DIMMode.Q3D:
node_pos += ni * nj * nk * 3 * 8
cell_pos += (ni - 1) * (nj - 1) * (nk - 1) * 8
elif g3d_world.options.dim_mode == DIMMode.G2D or g3d_world.options.dim_mode == DIMMode.G2D_AXISYMM:
node_pos += ni * nj * 2 * 8
cell_pos += (ni - 1) * (nj - 1) * 8
f.write(' <Domain>\n')
for im in range(nb):
ni, nj, nk = mesh.blocks[im].get_block_sizes()
f.write(' <Grid Name=\"Block %d\" GridType=\"Uniform\">\n' % (im + 1))
self.add_geo_attribute(im, ni, nj, nk, f, g3d_world.options.dim_mode)
item_counter = 2
self.add_cell_attribute(c_variables['ro']['longname'], im, f, item_counter)
for var in auxv_variable_list:
item_counter += 1
self.add_cell_attribute(a_variables[var]['longname'], im, f, item_counter)
for var in p_variables.keys():
item_counter += 1
self.add_cell_attribute(p_variables[var]['longname'], im, f, item_counter)
f.write(' </Grid>\n')
f.write(' </Domain>\n')
self.add_xdmf_footer(f)
f.close()
[docs]
def export_velocity_gradients(self, dom: 'Domain', vgrad: VGradField, **kwargs: Any) -> None:
"""Exports velocity gradient data
Parameters
----------
dom : Domain :
flow domain
vgrad : VGradField :
instance of velocity gradients
**kwargs : Any :
keyword-value pairs
valid keyword: 'name', 'export_name', 'xml_name', 'sol_dir', 'export_dir', 'xml_dir', 'remove_sub_path',
'label', 'subdir', 'variable_name', 'variable_names', 'no_xml', 'export_xml'
"""
g3d_world = G3DWorld()
self.__get_names(**kwargs, export_xml=True)
name = self.__names['name']
xml_name = self.__names['xml_name']
remove_sub_path = self.__names['remove_sub_path']
mesh = dom.mesh
msh = xml_name + '.geo'
if not os.path.isfile(msh):
mesh.export(name=xml_name)
v_variables = vgrad.export(name)
if len(remove_sub_path) != 0:
msh = msh.replace(remove_sub_path, '').strip('/')
for var in v_variables.keys():
v_variables[var]['filename'] = v_variables[var]['filename'].replace(remove_sub_path, '').strip('/')
if g3d_world.options.dim_mode.value > DIMMode.Q1D.value:
nb = mesh.n_blocks
bo = sys.byteorder
xmf = xml_name + '_vgrad.xmf'
xmf = clean_path(xmf)
print('generating xml meta data: %s' % xmf)
f = open(xmf, 'w')
self.add_xdmf_header(f)
node_pos = 0
cell_pos = 0
for im in range(nb):
ni, nj, nk = mesh.blocks[im].get_block_sizes()
f.write(' <DataItem Name=\"Collection %d\" ItemType=\"Collection\">\n' % (im + 1))
self.add_geo_data_item(ni, nj, nk, msh, f, node_pos, g3d_world.options.dim_mode, bo)
for var in v_variables.keys():
self.add_cell_data_item(ni, nj, nk, v_variables[var]['filename'], f,
cell_pos, g3d_world.options.dim_mode, bo)
f.write(' </DataItem>\n')
if g3d_world.options.dim_mode == DIMMode.G3D or g3d_world.options.dim_mode == DIMMode.Q3D:
node_pos += ni * nj * nk * 3 * 8
cell_pos += (ni - 1) * (nj - 1) * (nk - 1) * 8
elif g3d_world.options.dim_mode == DIMMode.G2D or g3d_world.options.dim_mode == DIMMode.G2D_AXISYMM:
node_pos += ni * nj * 2 * 8
cell_pos += (ni - 1) * (nj - 1) * 8
f.write(' <Domain>\n')
for im in range(nb):
ni, nj, nk = mesh.blocks[im].get_block_sizes()
f.write(' <Grid Name=\"Block %d\" GridType=\"Uniform\">\n' % (im + 1))
self.add_geo_attribute(im, ni, nj, nk, f, g3d_world.options.dim_mode)
item_counter = 1
for var in v_variables.keys():
item_counter += 1
self.add_cell_attribute(v_variables[var]['longname'], im, f, item_counter)
f.write(' </Grid>\n')
f.write(' </Domain>\n')
self.add_xdmf_footer(f)
f.close()
[docs]
def export_field(self, dom: 'Domain', field: FlowDataPlaceHolder, **kwargs: Any) -> None:
"""Exports field data to file
Parameters
----------
dom : Domain :
flow domain
field : FlowDataPlaceHolder :
instance of flow data placeholder
**kwargs : Any :
keyword-value pairs
valid keyword: 'name', 'export_name', 'xml_name', 'sol_dir', 'export_dir', 'xml_dir', 'remove_sub_path',
'label', 'subdir', 'variable_name', 'variable_names', 'no_xml', 'export_xml'
"""
g3d_world = G3DWorld()
self.__get_names(**kwargs, export_xml=False)
name = self.__names['name']
export_dir = self.__names['export_dir']
mesh = dom.mesh
msh = name + '.geo'
if not os.path.isfile(msh):
mesh.export(name=name)
variables = field.export(name)
if g3d_world.options.dim_mode.value > DIMMode.Q1D.value:
nb = mesh.n_blocks
bo = sys.byteorder
xmf = name + '.xmf'
msh = msh.strip(export_dir).strip('/')
for var in variables.keys():
variables[var]['filename'] = variables[var]['filename'].strip(export_dir).strip('/')
xmf = clean_path(xmf)
print('generating xml meta data: %s' % xmf)
f = open(xmf, 'w')
self.add_xdmf_header(f)
node_pos = 0
cell_pos = 0
for im in range(nb):
ni, nj, nk = mesh.blocks[im].get_block_sizes()
f.write(' <DataItem Name=\"Collection %d\" ItemType=\"Collection\">\n' % (im + 1))
self.add_geo_data_item(ni, nj, nk, msh, f, node_pos, g3d_world.options.dim_mode, bo)
for var in variables.keys():
self.add_cell_data_item(ni, nj, nk, variables[var]['filename'], f,
cell_pos, g3d_world.options.dim_mode, bo)
f.write(' </DataItem>\n')
if g3d_world.options.dim_mode == DIMMode.G3D or g3d_world.options.dim_mode == DIMMode.Q3D:
node_pos += ni * nj * nk * 3 * 8
cell_pos += (ni - 1) * (nj - 1) * (nk - 1) * 8
elif g3d_world.options.dim_mode == DIMMode.G2D or g3d_world.options.dim_mode == DIMMode.G2D_AXISYMM:
node_pos += ni * nj * 2 * 8
cell_pos += (ni - 1) * (nj - 1) * 8
f.write(' <Domain>\n')
for im in range(nb):
ni, nj, nk = mesh.blocks[im].get_block_sizes()
f.write(' <Grid Name=\"Block %d\" GridType=\"Uniform\">\n' % (im + 1))
self.add_geo_attribute(im, ni, nj, nk, f, g3d_world.options.dim_mode)
item_counter = 1
for var in variables.keys():
item_counter += 1
self.add_cell_attribute(variables[var]['longname'], im, f, item_counter)
f.write(' </Grid>\n')
f.write(' </Domain>\n')
self.add_xdmf_footer(f)
f.close()
[docs]
def export_scalar(self, dom: 'Domain', var: ndarray, **kwargs: Any) -> None:
"""Export scalar variable to file
Parameters
----------
dom : Domain :
flow domain
var : ndarray :
scalar variable array (cell values)
**kwargs : Any :
keyword-value pairs
valid keyword: 'name', 'export_name', 'xml_name', 'sol_dir', 'export_dir', 'xml_dir', 'remove_sub_path',
'label', 'subdir', 'variable_name', 'variable_names', 'no_xml', 'export_xml'
"""
g3d_world = G3DWorld()
self.__get_names(**kwargs, export_xml=False)
name = self.__names['name']
export_dir = self.__names['export_dir']
variable_name = self.__names['variable_name']
mesh = dom.mesh
msh = name + '.geo'
if not os.path.isfile(msh):
mesh.export(name=name)
n_cells = g3d_world.sizes.n_cells
nb = mesh.n_blocks
bo = sys.byteorder
xmf = name + '.xmf'
csv = name + '_' + variable_name + '.csv'
print('exporting scalar field to file: %s' % csv)
with open(csv, 'w+b') as f:
f.write(var[0:n_cells].tobytes())
if g3d_world.options.dim_mode.value > DIMMode.Q1D.value:
csv = csv.strip(export_dir).strip('/')
msh = msh.strip(export_dir).strip('/')
xmf = clean_path(xmf)
print('generating xml meta data: %s' % xmf)
f = open(xmf, 'w')
self.add_xdmf_header(f)
node_pos = 0
cell_pos = 0
for im in range(nb):
ni, nj, nk = mesh.blocks[im].get_block_sizes()
f.write(' <DataItem Name=\"Collection %d\" ItemType=\"Collection\">\n' % (im + 1))
self.add_geo_data_item(ni, nj, nk, msh, f, node_pos, g3d_world.options.dim_mode, bo)
self.add_cell_data_item(ni, nj, nk, csv, f, cell_pos, g3d_world.options.dim_mode, bo)
f.write(' </DataItem>\n')
if g3d_world.options.dim_mode == DIMMode.G3D or g3d_world.options.dim_mode == DIMMode.Q3D:
node_pos += ni * nj * nk * 3 * 8
cell_pos += (ni - 1) * (nj - 1) * (nk - 1) * 8
elif g3d_world.options.dim_mode == DIMMode.G2D or g3d_world.options.dim_mode == DIMMode.G2D_AXISYMM:
node_pos += ni * nj * 2 * 8
cell_pos += (ni - 1) * (nj - 1) * 8
f.write(' <Domain>\n')
for im in range(nb):
ni, nj, nk = mesh.blocks[im].get_block_sizes()
f.write(' <Grid Name=\"Block %d\" GridType=\"Uniform\">\n' % (im + 1))
self.add_geo_attribute(im, ni, nj, nk, f, g3d_world.options.dim_mode)
self.add_cell_attribute(variable_name, im, f)
f.write(' </Grid>\n')
f.write(' </Domain>\n')
self.add_xdmf_footer(f)
f.close()
[docs]
def export_scalars(self, dom: 'Domain', variables: list[ndarray], **kwargs: Any) -> None:
"""Export multiple scalar variables (arrays) to file (cell values)
Parameters
----------
dom : Domain :
flow domain
variables : list :
multiple arrays with cell values (list of arrays)
**kwargs : Any :
keyword-value pairs
valid keyword: 'name', 'export_name', 'xml_name', 'sol_dir', 'export_dir', 'xml_dir', 'remove_sub_path',
'label', 'subdir', 'variable_name', 'variable_names', 'no_xml', 'export_xml'
"""
g3d_world = G3DWorld()
n_var = len(variables)
self.__get_names(**kwargs, export_xml=False)
name = self.__names['name']
export_dir = self.__names['export_dir']
variable_names = self.__names['variable_names']
if len(variable_names) == 0:
for i in range(n_var):
variable_names.append('var_' + str(i))
mesh = dom.mesh
msh = name + '.geo'
if not os.path.isfile(msh):
mesh.export(name=name)
csv_files = []
for i in range(n_var):
csv_files.append(name + '_' + variable_names[i] + '.csv')
n_cells = g3d_world.sizes.n_cells
nb = mesh.n_blocks
bo = sys.byteorder
xmf = name + '.xmf'
for i in range(n_var):
print('exporting scalar field to file: %s' % csv_files[i])
with open(csv_files[i], 'w+b') as f:
f.write(variables[i][0:n_cells].tobytes())
csv_files[i] = csv_files[i].strip(export_dir).strip('/')
msh = msh.strip(export_dir).strip('/')
xmf = clean_path(xmf)
print('generating xml meta data: %s' % xmf)
f = open(xmf, 'w')
self.add_xdmf_header(f)
node_pos = 0
cell_pos = 0
for im in range(nb):
ni, nj, nk = mesh.blocks[im].get_block_sizes()
f.write(' <DataItem Name=\"Collection %d\" ItemType=\"Collection\">\n' % (im + 1))
self.add_geo_data_item(ni, nj, nk, msh, f, node_pos, g3d_world.options.dim_mode, bo)
for i in range(n_var):
self.add_cell_data_item(ni, nj, nk, csv_files[i], f, cell_pos, g3d_world.options.dim_mode, bo)
f.write(' </DataItem>\n')
if g3d_world.options.dim_mode == DIMMode.G3D or g3d_world.options.dim_mode == DIMMode.Q3D:
node_pos += ni * nj * nk * 3 * 8
cell_pos += (ni - 1) * (nj - 1) * (nk - 1) * 8
elif g3d_world.options.dim_mode == DIMMode.G2D or g3d_world.options.dim_mode == DIMMode.G2D_AXISYMM:
node_pos += ni * nj * 2 * 8
cell_pos += (ni - 1) * (nj - 1) * 8
f.write(' <Domain>\n')
for im in range(nb):
ni, nj, nk = mesh.blocks[im].get_block_sizes()
f.write(' <Grid Name=\"Block %d\" GridType=\"Uniform\">\n' % (im + 1))
self.add_geo_attribute(im, ni, nj, nk, f, g3d_world.options.dim_mode)
item_counter = 1
for i in range(n_var):
item_counter += 1
self.add_cell_attribute(variable_names[i], im, f, item_counter)
f.write(' </Grid>\n')
f.write(' </Domain>\n')
self.add_xdmf_footer(f)
f.close()
def __generate_2D_plot(self, X: ndarray, Y: ndarray, Z: ndarray, **kwargs: Any) -> None:
self.__get_names(**kwargs, export_xml=False, subdir='/images/2D/')
name = self.__names['name']
variable_name = self.__names['variable_name']
label = self.__names['label']
if label == '':
label = variable_name
fig = plt.figure()
plt.contourf(X, Y, Z, levels=100, cmap='jet')
color_bar = plt.colorbar(location='bottom')
color_bar.set_label(label)
plt.ylabel(r'$y\ [m]$')
plt.xlabel(r'$x\ [m]$')
plt.savefig(name + '_' + variable_name + '.png')
# plt.show()
plt.close(fig)
[docs]
def plot_scalar_2D(self, dom: 'Domain', var: ndarray, im: int = 0, k: int = 0, **kwargs: Any) -> None:
"""Plots scalar data in two dimensions
Parameters
----------
dom : Domain :
flow domain
var : ndarray :
scalar variable array (cell values)
im : int :
block number (Default value = 0)
k : int :
k-plane index (Default value = 0)
**kwargs : Any :
keyword-value pairs
valid keyword: 'name', 'export_name', 'xml_name', 'sol_dir', 'export_dir', 'xml_dir', 'remove_sub_path',
'label', 'subdir', 'variable_name', 'variable_names', 'no_xml', 'export_xml'
"""
mesh = dom.mesh
ni, nj, nk = mesh.blocks[im].get_block_sizes()
xc, yc, zc = dom.get_cell_centers()
X2D = np.zeros((ni - 1, nj - 1))
Y2D = np.zeros((ni - 1, nj - 1))
VAR2D = np.zeros((ni - 1, nj - 1))
for j in range(nj - 1):
for i in range(ni - 1):
kp = dom.get_cell(im, i, j, k)
X2D[i, j] = xc[kp]
Y2D[i, j] = yc[kp]
VAR2D[i, j] = var[kp]
self.__generate_2D_plot(X2D, Y2D, VAR2D, **kwargs)
[docs]
def plot_scalars_2D(self, dom: 'Domain', variables: ndarray, im: int = 0, k: int = 0, **kwargs: Any) -> None:
"""Plots scalar data in two dimensions (multiple scalar variables)
Parameters
----------
dom : Domain :
flow domain
variables : ndarray :
multiple arrays with cell values (list of arrays)
im : int :
block number (Default value = 0)
k : int :
k-plane index (Default value = 0)
**kwargs : Any :
keyword-value pairs
valid keyword: 'name', 'export_name', 'xml_name', 'sol_dir', 'export_dir', 'xml_dir', 'remove_sub_path',
'label', 'subdir', 'variable_name', 'variable_names', 'no_xml', 'export_xml'
"""
n_var = len(variables)
self.__get_names(**kwargs, export_xml=False)
variable_names = self.__names['variable_names']
if len(variable_names) == 0:
for i in range(n_var):
variable_names.append('var_' + str(i))
mesh = dom.mesh
ni, nj, nk = mesh.blocks[im].get_block_sizes()
xc, yc, zc = dom.get_cell_centers()
X2D = np.zeros((ni - 1, nj - 1))
Y2D = np.zeros((ni - 1, nj - 1))
VAR2D = np.zeros((ni - 1, nj - 1))
for j in range(nj - 1):
for i in range(ni - 1):
kp = dom.get_cell(im, i, j, k)
X2D[i, j] = xc[kp]
Y2D[i, j] = yc[kp]
for ivar in range(n_var):
for j in range(nj - 1):
for i in range(ni - 1):
kp = dom.get_cell(im, i, j, k)
VAR2D[i, j] = variables[ivar, kp]
self.__generate_2D_plot(X2D, Y2D, VAR2D, variable_name=variable_names[ivar], **kwargs)
[docs]
def plot_field_2D(self, dom: 'Domain', field: FlowDataPlaceHolder, im: int = 0, k: int = 0,
**kwargs: Any) -> None:
"""Plots field data in two dimensions (multiple variables)
Parameters
----------
dom : Domain :
flow domain
field : FlowDataPlaceHolder :
instance of flow data placeholder
im : int :
block number (Default value = 0)
k : int :
k-plane index (Default value = 0)
**kwargs : Any :
keyword-value pairs
valid keyword: 'name', 'export_name', 'xml_name', 'sol_dir', 'export_dir', 'xml_dir', 'remove_sub_path',
'label', 'subdir', 'variable_name', 'variable_names', 'no_xml', 'export_xml'
"""
variables = field.variables
mesh = dom.mesh
ni, nj, nk = mesh.blocks[im].get_block_sizes()
xc, yc, zc = dom.get_cell_centers()
X2D = np.zeros((ni - 1, nj - 1))
Y2D = np.zeros((ni - 1, nj - 1))
VAR2D = np.zeros((ni - 1, nj - 1))
for j in range(nj - 1):
for i in range(ni - 1):
kp = dom.get_cell(im, i, j, k)
X2D[i, j] = xc[kp]
Y2D[i, j] = yc[kp]
for var in variables.keys():
for j in range(nj - 1):
for i in range(ni - 1):
kp = dom.get_cell(im, i, j, k)
VAR2D[i, j] = variables[var]['ref'][kp]
self.__generate_2D_plot(X2D, Y2D, VAR2D, variable_name=variables[var]['longname'], **kwargs)
[docs]
def plot_flow_2D(self,
dom: 'Domain',
cons: ConsField,
auxv: AuxvField,
post: PostField,
im: int = 0,
k: int = 0,
**kwargs: Any) -> None:
"""Plots flow data in two dimensions (multiple variables)
Parameters
----------
dom : Domain :
flow domain
cons : ConsField :
instance of conservative variables
auxv : AuxvField :
instance of primitive variables
post : PostField :
instance of postprocessing variables
im : int :
block number (Default value = 0)
k : int :
k-plane index (Default value = 0)
**kwargs : Any :
keyword-value pairs
valid keyword: 'name', 'export_name', 'xml_name', 'sol_dir', 'export_dir', 'xml_dir', 'remove_sub_path',
'label', 'subdir', 'variable_name', 'variable_names', 'no_xml', 'export_xml'
"""
mesh = dom.mesh
ni, nj, nk = mesh.blocks[im].get_block_sizes()
xc, yc, zc = dom.get_cell_centers()
X2D = np.zeros((ni - 1, nj - 1))
Y2D = np.zeros((ni - 1, nj - 1))
VAR2D = np.zeros((ni - 1, nj - 1))
for j in range(nj - 1):
for i in range(ni - 1):
kp = dom.get_cell(im, i, j, k)
X2D[i, j] = xc[kp]
Y2D[i, j] = yc[kp]
for var in auxv.variables.keys():
V = auxv.get_array(var)
for j in range(nj - 1):
for i in range(ni - 1):
kp = dom.get_cell(im, i, j, k)
VAR2D[i, j] = V[kp]
self.__generate_2D_plot(X2D, Y2D, VAR2D, variable_name=auxv.variables[var]['longname'], **kwargs)
for var in post.variables.keys():
V = post.get_array(var)
for j in range(nj - 1):
for i in range(ni - 1):
kp = dom.get_cell(im, i, j, k)
VAR2D[i, j] = V[kp]
self.__generate_2D_plot(X2D, Y2D, VAR2D, variable_name=post.variables[var]['longname'], **kwargs)
var = 'ro'
V = cons.get_array(var)
for j in range(nj - 1):
for i in range(ni - 1):
kp = dom.get_cell(im, i, j, k)
VAR2D[i, j] = V[kp]
self.__generate_2D_plot(X2D, Y2D, VAR2D, variable_name=cons.variables[var]['longname'], **kwargs)
def __plot_probe_array(self, dom: 'Domain',
var: ndarray, lc: ndarray, **kwargs: Any) -> None:
self.__get_names(**kwargs, export_xml=False, subdir='/images/1D/')
name = self.__names['name']
variable_name = self.__names['variable_name']
xc, yc, zc = dom.get_cell_centers()
DX = xc[lc[1::]] - xc[lc[0:-1:]]
DY = yc[lc[1::]] - yc[lc[0:-1:]]
DZ = zc[lc[1::]] - zc[lc[0:-1:]]
DR = np.sqrt(DX ** 2 + DY ** 2 + DZ ** 2)
RC = np.zeros(len(lc))
for i in range(1, len(lc)):
RC[i] = RC[i - 1] + DR[i - 1]
RC = RC / max(RC)
fig = plt.figure()
plt.plot(RC, var[lc])
plt.xlabel('non-dimensional coordinate')
plt.ylabel(variable_name)
plt.xlim([0, max(RC)])
plt.savefig(name + '_' + variable_name + '.png')
# plt.show()
plt.close(fig)
[docs]
def plot_probe_array(self, dom: 'Domain', var: ndarray,
im: int, i0: int, j0: int, k0: int, idir: int, nci: int,
**kwargs: Any) -> None:
"""Plots probe array data
Parameters
----------
dom : Domain :
flow domain
var : ndarray :
scalar variable array (cell values)
im : int :
block number
i0 : int :
start index i-direction
j0 : int :
start index j-direction
k0 : int :
start index k-direction
idir : int :
probe direction (1 -> +i, 2 -> -i, 3 -> +j, 4 -> -j, 5 -> +k, 6 -> -k)
nci : int :
number of cells in specified direction
**kwargs : Any :
keyword-value pairs
valid keyword: 'name', 'export_name', 'xml_name', 'sol_dir', 'export_dir', 'xml_dir', 'remove_sub_path',
'label', 'subdir', 'variable_name', 'variable_names', 'no_xml', 'export_xml'
"""
mesh = dom.mesh
ni, nj, nk = mesh.blocks[im].get_block_sizes()
lc = np.zeros(nci, dtype=int)
l0c = dom.get_cell(im, i0, j0, k0)
ldic = self._id[idir] + (ni - 1) * self._jd[idir] + (ni - 1) * (nj - 1) * self._kd[idir]
for i in range(nci):
lc[i] = l0c + i * ldic
self.__plot_probe_array(dom, var, lc, **kwargs)