Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feat/sdk 24r2 #155

Merged
merged 15 commits into from
May 14, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions doc/.vale.ini
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ Vale.Terms = NO

# Apply the following styles
BasedOnStyles = Vale, Google
Vale.Terms = NO

# Removing Google-specific rule - Not applicable under some circumstances
Google.WordList = NO
Expand Down
5 changes: 4 additions & 1 deletion doc/source/api/examples/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,7 @@ Other PyTwin functions are available and used in :ref:`ref_example_gallery`.
:toctree: _autosummary

pytwin.download_file
pytwin.load_data
pytwin.load_data
pytwin.read_binary
pytwin.read_snapshot_size
pytwin.write_binary
6 changes: 3 additions & 3 deletions examples/02-tbrom_examples/00-TBROM_images.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@
import matplotlib.image as img
import matplotlib.pyplot as plt
import numpy as np
from pytwin import TwinModel, download_file
from pytwin import TwinModel, download_file, read_binary

twin_file = download_file("ThermalTBROM_23R1_other.twin", "twin_files", force_download=True)
cfd_file = download_file("T_Junction.cas.h5", "other_files", force_download=True)
Expand Down Expand Up @@ -80,8 +80,8 @@ def snapshot_to_cfd(snapshot_file, geometry_file, field_name, outputFilePath):
field of scalar data (temperature field).
"""

geometry_data = np.fromfile(geometry_file, dtype=np.double, offset=8).reshape(-1, 3)
snapshot_data = np.fromfile(snapshot_file, dtype=np.double, offset=8).reshape(-1, 1)
geometry_data = read_binary(geometry_file).reshape(-1, 3)
snapshot_data = read_binary(snapshot_file).reshape(-1, 1)
res_list = np.hstack((geometry_data, snapshot_data))

with open(outputFilePath, "w") as ipfile:
Expand Down
6 changes: 3 additions & 3 deletions examples/02-tbrom_examples/01-TBROM_dataTransfer_pyMAPDL.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@
from ansys.mapdl.core import launch_mapdl
import numpy as np
import pandas as pd
from pytwin import TwinModel, download_file
from pytwin import TwinModel, download_file, read_binary
import pyvista as pv

twin_file = download_file("ThermalTBROM_23R1_other.twin", "twin_files", force_download=True)
Expand Down Expand Up @@ -70,8 +70,8 @@ def snapshot_to_fea(snapshot_file, geometry_file):
"""Create a Pandas dataframe containing the x, y, z coordinates for the ROM
and snapshot file results."""

geometry_data = np.fromfile(geometry_file, dtype=np.double, offset=8).reshape(-1, 3)
snapshot_data = np.fromfile(snapshot_file, dtype=np.double, offset=8).reshape(-1, 1)
geometry_data = read_binary(geometry_file).reshape(-1, 3)
snapshot_data = read_binary(snapshot_file).reshape(-1, 1)
res_list = np.hstack((geometry_data, snapshot_data))

return pd.DataFrame(res_list)
Expand Down
4 changes: 2 additions & 2 deletions examples/02-tbrom_examples/03-TBROM_input_numpy_field.py
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@

import numpy as np
import pandas as pd
from pytwin import TwinModel, download_file
from pytwin import TwinModel, download_file, read_binary

twin_file = download_file("ThermalTBROM_FieldInput_23R1.twin", "twin_files", force_download=True)
inputfieldsnapshot = download_file("TEMP_1.bin", "twin_input_files/inputFieldSnapshots", force_download=True)
Expand All @@ -78,7 +78,7 @@ def unflatten_vector(vector: np.ndarray, dimensionality: int):
################################################################################
# Read one vector input from a file (this input could have been generated by a
# separate program).
temperature_array = np.fromfile(inputfieldsnapshot, dtype=np.double, offset=8)
temperature_array = read_binary(inputfieldsnapshot)

################################################################################
# Enter information regarding TBROM, input fields and output named selection
Expand Down
1 change: 1 addition & 0 deletions src/ansys/pytwin/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@
"""
PUBLIC API TO PYTWIN EVALUATE
"""
from pytwin.evaluate.tbrom import read_binary, read_snapshot_size, write_binary
from pytwin.evaluate.twin_model import TwinModel, TwinModelError

"""
Expand Down
241 changes: 150 additions & 91 deletions src/ansys/pytwin/evaluate/tbrom.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,148 @@
import pyvista as pv


def read_binary(filepath):
"""
Read a binary snapshot file from the disk.

Parameters
----------
filepath : str
Path of the binary file to be read.

Returns
-------
np.ndarray
Return a 1D flatenned Numpy array of snapshot data read.

Examples
--------
>>> from pytwin import write_binary
>>> snapshot_data = read_binary('snapshot.bin')
"""
return np.fromfile(filepath, dtype=np.double, offset=8).reshape(
-1,
)


def write_binary(filepath: str, vec: np.ndarray):
"""
Write a binary snapshot file on the disk.

Parameters
----------
filepath : str
Path of the binary file to be written.
vec : np.ndarray
N-dimensional Numpy array of snapshot data to be written in binary file.

Returns
-------
bool
Return True if the binary file is successfully written.

Examples
--------
>>> from pytwin import write_binary
>>> scalar_field = np.ndarray([1.0, 2.0, 3.0, 5.0])
>>> write_binary('snapshot_scalar.bin', scalar_field)
>>> vector_field = np.ndarray([[1.0, 1.0, 0.0], [1.0, 2.0, 3.0], [5.0, 3.0, 3.0], [5.0, 5.0, 6.0]])
>>> write_binary('snapshot_vector.bin', vector_field)
"""
vec = vec.reshape(
-1,
)
if os.path.exists(filepath):
os.remove(filepath)
with open(filepath, "xb") as f:
f.write(struct.pack("Q", len(vec)))
vec.tofile(f)
return True


def read_snapshot_size(filepath):
"""
Return the number of data stored in a snapshot binary file.

Parameters
----------
filepath : str
Path of the binary file to be written.

Returns
-------
int
Number of data stored in the binary file.

Examples
--------
>>> from pytwin import write_binary
>>> number_data = read_snapshot_size('snapshot.bin')
"""
with open(filepath, "rb") as f:
nbdof = struct.unpack("Q", f.read(8))[0]
return nbdof


def _read_basis(filepath):
with open(filepath, "rb") as f:
var = struct.unpack("cccccccccccccccc", f.read(16))[0]
nb_val = struct.unpack("Q", f.read(8))[0]
nb_mc = struct.unpack("Q", f.read(8))[0]
return np.fromfile(f, dtype=np.double, offset=0).reshape(-1, nb_val)


def _read_settings(filepath):
with open(filepath) as f:
data = json.load(f)

namedselection = {}
dimensionality = None
name = None
unit = None

if "namedSelections" in data:
namedselection = data["namedSelections"]
if "dimensionality" in data:
dimensionality = data["dimensionality"]
if "name" in data:
name = data["name"]
if "unit" in data:
unit = data["unit"]

tbromns = dict()
outputname = name.replace(" ", "_")

# Create list of name selections indexes
for name, idsList in namedselection.items():
idsListNp = np.array(idsList)
ind = np.where(idsListNp == -1)
i = 0
for elem in np.nditer(ind):
subarray = np.arange(idsListNp[elem - 1 - i] + 1, idsListNp[elem + 1 - i])
idsListNp = np.delete(idsListNp, elem - i)
idsListNp = np.concatenate((idsListNp, subarray))
i = i + 1
tbromns.update({name: idsListNp})

return [tbromns, dimensionality, outputname, unit]


def _read_properties(filepath):
with open(filepath) as f:
data = json.load(f)

fields = {}
if "fields" in data:
fields = data["fields"]
out_field = fields["outField"]

nb_points = out_field["nbDof"]
nb_modes = out_field["nbModes"]

return [nb_points, nb_modes]


class TbRom:
"""
Instantiates a TBROM that is part of a TWIN file created by Ansys Twin Builder.
Expand Down Expand Up @@ -55,20 +197,20 @@ def __init__(self, tbrom_name: str, tbrom_path: str):
folder = file.split("_")
fname = folder[1]
inpath = os.path.join(tbrom_path, file, TbRom.TBROM_BASIS)
inbasis = TbRom._read_basis(inpath)
inbasis = _read_basis(inpath)
infdata.update({fname: inbasis})
self._infbasis = infdata

settingspath = os.path.join(tbrom_path, TbRom.OUT_F_KEY, TbRom.TBROM_SET)
[nsidslist, dimensionality, outputname, unit] = TbRom._read_settings(settingspath)
[nsidslist, dimensionality, outputname, unit] = _read_settings(settingspath)
self._nsidslist = nsidslist
self._outdim = int(dimensionality[0])
self._outname = outputname
self._outunit = unit
self._outputfilespath = None

propertiespath = os.path.join(tbrom_path, TbRom.TBROM_PROP)
[nbpoints, nbmodes] = TbRom._read_properties(propertiespath)
[nbpoints, nbmodes] = _read_properties(propertiespath)
self._nbpoints = int(nbpoints / self._outdim)
self._nbmodes = nbmodes

Expand Down Expand Up @@ -97,7 +239,7 @@ def _generate_points(self, on_disk: bool, output_file_path: str, named_selection
"""
vec = self._data_extract(named_selection, self._pointsdata.points)
if on_disk:
TbRom.write_binary(output_file_path, vec)
write_binary(output_file_path, vec)
return output_file_path
else:
return vec
Expand All @@ -123,7 +265,7 @@ def _generate_snapshot(self, on_disk: bool, output_file_path: str, named_selecti
"""
vec = self._data_extract(named_selection, self._pointsdata[self.field_output_name])
if on_disk:
TbRom.write_binary(output_file_path, vec)
write_binary(output_file_path, vec)
return output_file_path
else:
return vec
Expand All @@ -144,7 +286,7 @@ def _reduce_field_input(self, name: str, snapshot: Union[str, Path, np.ndarray])
if isinstance(snapshot, np.ndarray):
vecnp = snapshot
else:
vecnp = TbRom.read_binary(snapshot)
vecnp = read_binary(snapshot)

if name is None or self.field_input_count == 1:
basis = list(self._infbasis.values())[0]
Expand Down Expand Up @@ -240,7 +382,7 @@ def _data_extract(self, named_selection: str, data: np.ndarray):

def _read_points(self, filepath):
if os.path.exists(filepath):
points = TbRom.read_binary(filepath)
points = read_binary(filepath)
has_point_file = True
else:
points = np.zeros(3 * self.nb_points)
Expand All @@ -249,94 +391,11 @@ def _read_points(self, filepath):
return has_point_file

def _init_pointsdata(self, filepath):
self._outbasis = TbRom._read_basis(filepath).reshape(self.nb_modes, self.nb_points, self.field_output_dim)
self._outbasis = _read_basis(filepath).reshape(self.nb_modes, self.nb_points, self.field_output_dim)
# initialize output field data
if self._hasoutmcs:
self._pointsdata[self.field_output_name] = np.zeros((self.nb_points, self.field_output_dim))

@staticmethod
def read_binary(filepath):
return np.fromfile(filepath, dtype=np.double, offset=8).reshape(
-1,
)

@staticmethod
def write_binary(filepath, vec):
vec = vec.reshape(
-1,
)
if os.path.exists(filepath):
os.remove(filepath)
with open(filepath, "xb") as f:
f.write(struct.pack("Q", len(vec)))
vec.tofile(f)
return True

@staticmethod
def _read_basis(filepath):
with open(filepath, "rb") as f:
var = struct.unpack("cccccccccccccccc", f.read(16))[0]
nb_val = struct.unpack("Q", f.read(8))[0]
nb_mc = struct.unpack("Q", f.read(8))[0]
return np.fromfile(f, dtype=np.double, offset=0).reshape(-1, nb_val)

@staticmethod
def _read_settings(filepath):
with open(filepath) as f:
data = json.load(f)

namedselection = {}
dimensionality = None
name = None
unit = None

if "namedSelections" in data:
namedselection = data["namedSelections"]
if "dimensionality" in data:
dimensionality = data["dimensionality"]
if "name" in data:
name = data["name"]
if "unit" in data:
unit = data["unit"]

tbromns = dict()
outputname = name.replace(" ", "_")

# Create list of name selections indexes
for name, idsList in namedselection.items():
idsListNp = np.array(idsList)
ind = np.where(idsListNp == -1)
i = 0
for elem in np.nditer(ind):
subarray = np.arange(idsListNp[elem - 1 - i] + 1, idsListNp[elem + 1 - i])
idsListNp = np.delete(idsListNp, elem - i)
idsListNp = np.concatenate((idsListNp, subarray))
i = i + 1
tbromns.update({name: idsListNp})

return [tbromns, dimensionality, outputname, unit]

@staticmethod
def _read_properties(filepath):
with open(filepath) as f:
data = json.load(f)

fields = {}
if "fields" in data:
fields = data["fields"]
out_field = fields["outField"]

nb_points = out_field["nbDof"]
nb_modes = out_field["nbModes"]

return [nb_points, nb_modes]

@staticmethod
def _read_snapshot_size(filepath):
with open(filepath, "rb") as f:
nbdof = struct.unpack("Q", f.read(8))[0]
return nbdof

@property
def has_point_file(self):
return self._has_point_file
Expand Down
Loading
Loading