Skip to content
Open
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
38 changes: 29 additions & 9 deletions flowboost/openfoam/data/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -97,21 +97,39 @@ def discover_function_objects(self) -> dict[str, dict[str, list[Path]]]:

function_objects = {}
for function_dir in filter(Path.is_dir, self.post_processing_path.iterdir()):
time_dirs = self._time_dirs_for_function_object(function_dir)

function_objects[function_dir.name] = {
time_dir.name: sorted(
(path for path in time_dir.iterdir() if path.is_file()),
key=lambda path: path.name,
)
for time_dir in time_dirs
}
direct_outputs = self._files_by_time_directory(function_dir)
if direct_outputs:
function_objects[function_dir.name] = direct_outputs

# Multi-region function objects often add one extra nesting level:
# postProcessing/<region>/<functionObject>/<time>/...
for nested_function_dir in filter(Path.is_dir, function_dir.iterdir()):
nested_outputs = self._files_by_time_directory(nested_function_dir)
if nested_outputs:
function_objects[
f"{function_dir.name}/{nested_function_dir.name}"
] = nested_outputs

return function_objects

def _time_dirs_for_function_object(self, fo_folder: Path) -> list[Path]:
return list(filter(Path.is_dir, fo_folder.iterdir()))

def _files_by_time_directory(self, fo_folder: Path) -> dict[str, list[Path]]:
"""Return a time->files mapping when *fo_folder* has standard output."""
time_dirs = self._time_dirs_for_function_object(fo_folder)
outputs = {
time_dir.name: sorted(
(path for path in time_dir.iterdir() if path.is_file()),
key=lambda path: path.name,
)
for time_dir in time_dirs
}

# Only treat the folder as a function-object output when at least one
# time directory contains files.
return {time: files for time, files in outputs.items() if files}

# -- simple_function_object_reader ------------------------------------

@overload
Expand Down Expand Up @@ -160,6 +178,8 @@ def simple_function_object_reader(
at_time=at_time,
)

function_object_name = function_object_name.strip("/")

function_objects = self.discover_function_objects()

if function_object_name not in function_objects:
Expand Down
39 changes: 39 additions & 0 deletions tests/flowboost/openfoam/test_data_unit.py
Original file line number Diff line number Diff line change
Expand Up @@ -196,3 +196,42 @@ def test_simple_reader_loads_single_extensionless_output(self, tmp_path):
{"column_1": 0.1, "column_2": 1.0},
{"column_1": 0.2, "column_2": 2.0},
]

def test_discovers_multiregion_function_objects(self, tmp_path):
fo_file = (
tmp_path
/ "postProcessing"
/ "fluid"
/ "cylinderT"
/ "0"
/ "surfaceFieldValue.dat"
)
fo_file.parent.mkdir(parents=True)
fo_file.write_text("# Time\tareaAverage(T)\n0.1\t297.0\n0.2\t298.0\n")

data = PolarsData(path=tmp_path)
discovered = data.discover_function_objects()

assert discovered["fluid/cylinderT"]["0"] == [fo_file]

def test_simple_reader_loads_multiregion_function_object(self, tmp_path):
fo_file = (
tmp_path
/ "postProcessing"
/ "fluid"
/ "cylinderT"
/ "0"
/ "surfaceFieldValue.dat"
)
fo_file.parent.mkdir(parents=True)
fo_file.write_text("# Time\tareaAverage(T)\n0.1\t297.0\n0.2\t298.0\n")

data = PolarsData(path=tmp_path)
df = data.simple_function_object_reader("/fluid/cylinderT")

assert df is not None
assert df.columns == ["Time", "areaAverage(T)"]
assert df.to_dicts() == [
{"Time": 0.1, "areaAverage(T)": 297.0},
{"Time": 0.2, "areaAverage(T)": 298.0},
]
Loading