Skip to content

Commit

Permalink
reverting fluent gui; more fluent checks
Browse files Browse the repository at this point in the history
  • Loading branch information
SteveDoyle2 committed Oct 16, 2024
1 parent 92a8fea commit 2f89c9a
Show file tree
Hide file tree
Showing 5 changed files with 174 additions and 40 deletions.
19 changes: 19 additions & 0 deletions pyNastran/converters/fluent/fluent.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,14 @@ def __init__(self, auto_read_write_h5: bool=True,
self.auto_read_write_h5 = auto_read_write_h5
self.log = get_logger2(log=log, debug=debug)

self.node_id = np.array([], dtype='int32')
self.xyz = np.zeros((0, 3), dtype='int32')
self.element_id = np.array([], dtype='int32')
self.quads = np.zeros((0, 6), dtype='int32')
self.tris = np.zeros((0, 5), dtype='int32')
self.titles = []
self.results = np.zeros((0, 0), dtype='float64')

def _get_h5_filename(self, h5_filename: PathLike) -> str:
if h5_filename == '':
base, ext = os.path.splitext(self.fluent_filename)
Expand Down Expand Up @@ -121,6 +129,12 @@ def read_fluent(self, fluent_filename: PathLike) -> None:
#self.tri_pressure = tri_

def write_fluent(self, fluent_filename: str) -> None:
assert len(self.node_id) > 0, self.node_id
assert len(self.node_id) == len(self.xyz)
assert self.tris.shape[1] == 5, self.tris.shape
assert self.quads.shape[1] == 6, self.quads.shape
assert len(self.element_id) > 0, self.element_id

base, ext = os.path.splitext(fluent_filename)
vrt_filename = base + '.vrt'
daten_filename = base + '.daten'
Expand Down Expand Up @@ -229,6 +243,11 @@ def write_cell(vrt_filename: PathLike, quads: np.ndarray, tris: np.ndarray) -> N
dim_fmt = '%-8d %8s %8s %8d %8s\n'
tri_fmt = '%-8d %8s %8s %8s\n'
quad_fmt = '%-8d %8s %8s %8s %8s\n'

ntri, ntri_col = tris.shape
nquad, nquad_col = quads.shape
assert ntri_col == 5, tris.shape
assert nquad_col == 6, quads.shape
with open(vrt_filename, 'w') as cel_file:
# row1 = [eid, dim, pid, 3, 4]
# row2 = [eid, n1, n2, n3, n4]
Expand Down
117 changes: 77 additions & 40 deletions pyNastran/converters/fluent/fluent_io.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,68 +34,77 @@ def load_fluent_geometry(self, fld_filename: str,
return

log = self.gui.log
model = read_fluent(fld_filename, log=log, debug=False)
model = read_fluent(
fld_filename, auto_read_write_h5=False,
log=log, debug=False)
#self.model_type = model.model_type

#self.node = node
node_id = model.node_id
nodes = model.xyz
#self.element_id = element_id
tris = model.tris
quads = model.quads
nnodes = len(nodes)

# support multiple results
titles = model.titles
results = model.results

element_id = model.element_id #np.arange(1, nelement+1)
#assert np.array_equal(element_id, np.unique(element_id))

# we reordered the tris/quads to be continuous to make them easier to add
iquad = np.searchsorted(element_id, quads[:, 0])
itri = np.searchsorted(element_id, tris[:, 0])

quad_results = results[iquad, :]
tri_results = results[itri, :]

region = np.hstack([quads[:, 1], tris[:, 1]])
results = np.vstack([quad_results, tri_results])
nquad = len(quads)
ntri = len(tris)
nelement = nquad + ntri
log.debug(f'results.shape = {results.shape}')

node_id = model.node_id
nnodes = len(nodes)
assert len(element_id) == len(region)
if 1:
element_id = model.element_ids
region = model.region
elements_list = model.elements_list
nelement = len(element_id)
is_list = True
else: # pragma: no cover
is_list = False
tris = model.tris
quads = model.quads

element_id = model.element_id #np.arange(1, nelement+1)
assert np.array_equal(element_id, np.unique(element_id))
assert len(element_id) == len(region)

# we reordered the tris/quads to be continuous to make them easier to add
iquad = np.searchsorted(element_id, quads[:, 0])
itri = np.searchsorted(element_id, tris[:, 0])

quad_results = results[iquad, :]
tri_results = results[itri, :]

region = np.hstack([quads[:, 1], tris[:, 1]])
results = np.vstack([quad_results, tri_results])
nquad = len(quads)
ntri = len(tris)
nelement = nquad + ntri
log.debug(f'results.shape = {results.shape}')

self.gui.nnodes = nnodes
self.gui.nelements = nelement

self.gui.log.info('nnodes=%s nelements=%s' % (self.gui.nnodes, self.gui.nelements))
grid = self.gui.grid
grid.Allocate(self.gui.nelements, 1000)
ugrid = self.gui.grid
ugrid.Allocate(self.gui.nelements, 1000)

assert nodes is not None
points = numpy_to_vtk_points(nodes)
_create_elements(grid, node_id, model.quads, model.tris)

assert len(element_id) == len(region)
ugrid.SetPoints(points)
log.info(f'created vtk points')
self.gui.nid_map = {}
#elem.SetNumberOfPoints(nnodes)

assert nodes is not None
xmax, ymax, zmax = nodes.max(axis=0)
xmin, ymin, zmin = nodes.min(axis=0)
self.gui.log.info('xmax=%s xmin=%s' % (xmax, xmin))
self.gui.log.info('ymax=%s ymin=%s' % (ymax, ymin))
self.gui.log.info('zmax=%s zmin=%s' % (zmax, zmin))
log.info('xmax=%s xmin=%s' % (xmax, xmin))
log.info('ymax=%s ymin=%s' % (ymax, ymin))
log.info('zmax=%s zmin=%s' % (zmax, zmin))
dim_max = max(xmax-xmin, ymax-ymin, zmax-zmin)
self.gui.create_global_axes(dim_max)

assert len(node_id) == len(np.unique(node_id))
if is_list:
_create_elements_list(ugrid, node_id, elements_list)
else:
_create_elements(ugrid, node_id, model.quads, model.tris)
log.info(f'created vtk elements')

grid.SetPoints(points)
grid.Modified()
self.gui.nid_map = {}
self.gui.create_global_axes(dim_max)

ugrid.Modified()

# loadSTLResults - regions/loads
self.gui.scalar_bar_actor.VisibilityOff()
Expand All @@ -116,6 +125,34 @@ def load_fluent_geometry(self, fld_filename: str,
self.gui._finish_results_io2(model_name, form, cases)
log.info(f'finished')

def _create_elements_list(ugrid: vtkUnstructuredGrid,
node_id: np.ndarray,
elements_list: list[list[int]]):
assert np.array_equal(node_id, np.unique(node_id))
assert node_id.min() >= 0, node_id.min()
nid_to_index = {nid : i for i, nid in enumerate(node_id)}
#print(min(node_id), max(node_id))

for facei in elements_list:
face = np.array(facei, dtype='int32') # cast str to int
if len(face) == 3:
elem = vtkTriangle()
epoints = elem.GetPointIds()
epoints.SetId(0, nid_to_index[face[0]])
epoints.SetId(1, nid_to_index[face[1]])
epoints.SetId(2, nid_to_index[face[2]])
ugrid.InsertNextCell(5, epoints)
elif len(face) == 4:
elem = vtkQuad()
epoints = elem.GetPointIds()
epoints.SetId(0, nid_to_index[face[0]])
epoints.SetId(1, nid_to_index[face[1]])
epoints.SetId(2, nid_to_index[face[2]])
epoints.SetId(3, nid_to_index[face[3]])
ugrid.InsertNextCell(9, epoints)
else: # pragma: no cover
raise RuntimeError(face)

def _create_elements(ugrid: vtkUnstructuredGrid,
node_ids: np.ndarray,
tris: np.ndarray,
Expand Down
8 changes: 8 additions & 0 deletions pyNastran/converters/fluent/test_fluent.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,15 @@
from pyNastran.converters.fluent.nastran_to_fluent import nastran_to_fluent
from pyNastran.converters.fluent.fluent_to_tecplot import fluent_to_tecplot
from pyNastran.converters.tecplot.tecplot import read_tecplot
from pyNastran.converters.fluent.ugrid_to_fluent import ugrid_to_fluent_filename

warnings.simplefilter('always')
np.seterr(all='raise')

PKG_PATH = pyNastran.__path__[0]
BWB_PATH = Path(os.path.join(PKG_PATH, '..', 'models', 'bwb'))
TEST_PATH = Path(os.path.join(PKG_PATH, 'converters', 'fluent'))
UGRID_PATH = os.path.join(PKG_PATH, 'converters', 'aflr', 'ugrid', 'models')


class TestFluent(unittest.TestCase):
Expand Down Expand Up @@ -98,6 +100,12 @@ def test_nastran_to_fluent(self):
tecplot = fluent_to_tecplot(vrt_filename, tecplot_filename)
#read_tecplot(tecplot_filename) # TODO: fix tecplot parsing; the file is correct...

def test_ugrid3d_gui_box(self):
"""simple UGRID3D box model"""
ugrid_filename = os.path.join(UGRID_PATH, 'box.b8.ugrid')
fluent_filename = os.path.join(UGRID_PATH, 'box.vrt')
fluent_model = ugrid_to_fluent_filename(ugrid_filename, fluent_filename)

def main(): # pragma: no cover
import time
time0 = time.time()
Expand Down
15 changes: 15 additions & 0 deletions pyNastran/converters/fluent/test_fluent_gui.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,14 @@
#from pyNastran.bdf.bdf import BDF
from pyNastran.converters.fluent.fluent_io import FluentIO
from pyNastran.converters.fluent.nastran_to_fluent import nastran_to_fluent
from pyNastran.converters.fluent.ugrid_to_fluent import ugrid_to_fluent_filename


PKG_PATH = Path(pyNastran.__path__[0])
MODEL_PATH = PKG_PATH / '..' / 'models'
BWB_PATH = MODEL_PATH / 'bwb'
TEST_PATH = PKG_PATH / 'converters' / 'fluent'
UGRID_PATH = os.path.join(PKG_PATH, 'converters', 'aflr', 'ugrid', 'models')


class FluentGui(FakeGUIMethods):
Expand All @@ -39,10 +41,23 @@ def test_fluent_geometry_01(self):
tecplot_filename = BWB_PATH / 'bwb_saero.plt'
nastran_to_fluent(nastran_filename, vrt_filename, log=log)

log = get_logger(level='warning', encoding='utf-8')
test = FluentGui()
test.log = log
test.on_load_geometry(vrt_filename, geometry_format='fluent', stop_on_failure=True)

def test_fluent_gui_ugrid3d_gui_box(self):
"""simple UGRID3D box model"""
ugrid_filename = os.path.join(UGRID_PATH, 'box.b8.ugrid')
fluent_filename = os.path.join(UGRID_PATH, 'box.vrt')
fluent_model = ugrid_to_fluent_filename(ugrid_filename, fluent_filename)

log = get_logger(level='warning', encoding='utf-8')
test = FluentGui()
test.log = log
test.on_load_geometry(
fluent_filename, geometry_format='fluent', stop_on_failure=True)


if __name__ == '__main__': # pragma: no cover
unittest.main()
55 changes: 55 additions & 0 deletions pyNastran/converters/fluent/ugrid_to_fluent.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
import numpy as np
from pyNastran.utils import PathLike
from pyNastran.converters.aflr.ugrid.ugrid_reader import read_ugrid
from pyNastran.converters.fluent.fluent import Fluent, read_fluent

def ugrid_to_fluent_filename(ugrid_filename: PathLike,
fluent_filename: PathLike) -> Fluent:
model = ugrid_to_fluent(ugrid_filename)
model.write_fluent(fluent_filename)
return model

def ugrid_to_fluent(ugrid_filename: PathLike) -> Fluent:
ugrid_model = read_ugrid(ugrid_filename)
fluent_model = Fluent(auto_read_write_h5=False)

# self.nodes = np.array([], dtype='float32')
# self.tris = np.array([], dtype='int32')
# self.quads = np.array([], dtype='int32')
# self.pids = np.array([], dtype='int32')

# self.tets = np.array([], dtype='int32')
# self.penta5s = np.array([], dtype='int32')
# self.penta6s = np.array([], dtype='int32')
# self.hexas = np.array([], dtype='int32')
nnodes = len(ugrid_model.nodes)
ntri = len(ugrid_model.tris)
nquad = len(ugrid_model.quads)
neids = ntri + nquad
assert neids > 0, (ntri, nquad)
element_id = np.arange(1, neids+1)
property_id = ugrid_model.pids

eid_tri = element_id[:ntri]
eid_quad = element_id[ntri:]
pid_tri = property_id[:ntri]
pid_quad = property_id[ntri:]
assert len(eid_quad) == nquad
if ntri:
assert len(eid_tri) == ntri
tris = np.column_stack([eid_tri, pid_tri, ugrid_model.tris])
print(ugrid_model.tris.shape, tris.shape)
assert tris.shape[1] == 6, tris.shape
fluent_model.tris = tris

if nquad:
quads = np.column_stack([eid_quad, pid_quad, ugrid_model.quads])
assert quads.shape[1] == 6, quads.shape
fluent_model.quads = quads

fluent_model.node_id = np.arange(1, nnodes+1)
fluent_model.xyz = ugrid_model.nodes
fluent_model.element_id = element_id
fluent_model.titles = ['ShellID', 'PropertyID']
fluent_model.results = property_id.reshape((neids, 1))
return fluent_model

0 comments on commit 2f89c9a

Please sign in to comment.