Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
102 commits
Select commit Hold shift + click to select a range
68a360f
template case and utilities to move spargers
malihass May 21, 2025
eb12b72
fix presteps
May 21, 2025
ff27108
get rid of all multiphaseEulerFoam ref
malihass May 22, 2025
45fa2cd
add a troubleshoot page to help users
malihass May 22, 2025
7c14a97
discuss the bdofoam problem
malihass May 22, 2025
63df543
update v since pypi package will change
malihass May 22, 2025
8ca4585
add test for case generation
malihass May 23, 2025
980ec07
fix format
malihass May 23, 2025
d947ba0
make sure test passes
malihass May 23, 2025
4f75b72
missing module
malihass May 23, 2025
af9b55f
include case gen data to package
malihass May 23, 2025
aa1d8b9
trigger ci
malihass May 23, 2025
29fb8a1
explicit inclusion of constant
malihass May 23, 2025
5b53e0d
print what github action actually copied
malihass May 23, 2025
ff0185e
revert log
malihass May 23, 2025
db72292
all tests
malihass May 23, 2025
8e761f8
prepare for merge
malihass May 23, 2025
b331b4b
Merge pull request #105 from NREL/movespargci
malihass May 23, 2025
a56282d
Create temp
jainprana May 30, 2025
65e172e
Add files via upload
jainprana May 30, 2025
b74c870
fix format
malihass May 30, 2025
e1382f6
fix typos in readme
malihass May 30, 2025
00bdb3d
typo in pickle import
malihass May 30, 2025
a310482
add dependencies to setup
malihass May 30, 2025
3dbb892
add doc and type hinting
malihass May 30, 2025
5c0c719
split surrogate and optimization
malihass May 30, 2025
188e7b6
doc string type hinting and reuse surrogate functions
malihass May 30, 2025
753582e
ignore pdf from codespelling
malihass May 30, 2025
aabba8c
Merge pull request #107 from jainprana/Discrete_Optimization
malihass May 30, 2025
d6b0c39
fix concentration computation and default cstar
malihass Jun 5, 2025
df26bd5
replace script in data gen
malihass Jun 5, 2025
a9644c6
save optim results to folder, and remove tmp files
malihass Jun 5, 2025
73245fe
add script to generate paper figures
malihass Jun 9, 2025
220de6b
Merge pull request #109 from NREL/optimformat
malihass Jun 9, 2025
0b29067
remove tabs
malihass Jun 16, 2025
5af30ba
add a check for tabs in yaml files
malihass Jun 16, 2025
c4a09ec
use the yaml parse function instead of rewriting it
malihass Jun 16, 2025
e8fddb5
sparger overlap capability
malihass Jun 16, 2025
427f163
add overlapping patches to doc
malihass Jun 16, 2025
6561076
larger image
malihass Jun 16, 2025
eff5636
Merge pull request #110 from NREL/strerr
malihass Jun 17, 2025
7b1bfff
update the ci to test python 3.13
malihass Jun 17, 2025
9e0db3b
remove intermediate python tests
malihass Jun 17, 2025
2b950b3
Merge pull request #111 from NREL/pyupdate
malihass Jun 17, 2025
c5e1fa6
document ofio
malihass Jul 8, 2025
c5b79b2
remove data from package
malihass Jul 8, 2025
26a51f5
add tests for dictionary reading
malihass Jul 8, 2025
ac71303
show how to read a control dict
malihass Jul 8, 2025
4134b94
remove too strict assertion
malihass Jul 8, 2025
73e1cb9
format
malihass Jul 8, 2025
587ec49
update version
malihass Jul 8, 2025
fd69f6b
remove config files
malihass Jul 8, 2025
bac6e15
remove unused imports and format
malihass Jul 9, 2025
e5f7f10
docstring for tests
malihass Jul 9, 2025
f017303
Merge pull request #112 from NREL/ofio_cleanup
malihass Jul 9, 2025
2511102
centralize postprocess
malihass Jul 9, 2025
d0d77b9
test bubble diameter calculation
malihass Jul 9, 2025
1789d0c
remove rogue val dict
malihass Jul 9, 2025
1f7c87c
push to pypi to pass test
malihass Jul 9, 2025
8f7cc18
Merge pull request #113 from NREL/postcleanup
malihass Jul 9, 2025
7069e23
superficial velocity calculation
malihass Jul 9, 2025
a139d17
update bird version
malihass Jul 9, 2025
393e338
add flat panel reactor tutorial and add it to the ci
malihass Jul 9, 2025
4706d99
adding ref and only run 1 timestep
malihass Jul 9, 2025
0b5b7be
Merge pull request #114 from NREL/flat_panel
malihass Jul 9, 2025
bdda423
add a better contributing guideline
malihass Jul 10, 2025
dc55a82
add description of python interface
malihass Jul 10, 2025
483b731
fix display of python versions
malihass Jul 10, 2025
4baca52
Merge pull request #115 from NREL/pythoninterfacedoc
malihass Jul 10, 2025
5f813a5
syncup
malihass Jul 10, 2025
5b3edf8
remove useless hidden files
malihass Jul 10, 2025
f605aff
remove old job script
malihass Jul 10, 2025
eb07db5
remove duplicated case
malihass Jul 10, 2025
4af29c5
use path lib instead of in package data
malihass Jul 10, 2025
27c1b43
use post_quantities functions for the history
malihass Jul 10, 2025
4eff33d
format
malihass Jul 10, 2025
025be6a
test everything
malihass Jul 10, 2025
b07d600
specify nrel-bird version in ci
malihass Jul 10, 2025
760181b
Merge pull request #104 from NREL/movesparg
malihass Jul 10, 2025
f4c04e1
make sure prestep and run fail if any command fails
malihass Jul 15, 2025
8e41c00
fail fast experimental cases
malihass Jul 15, 2025
e3f2ee9
we do not use force sign anymore
malihass Jul 15, 2025
66f0c07
add boiler plate post process doc
malihass Jul 15, 2025
5b21d40
replace conv2 with conv in the new read history scripts
malihass Jul 15, 2025
77decd1
do the trap after module load (seems like a lot of failure can happen…
malihass Jul 15, 2025
e9beae0
setup logger and init it once
malihass Jul 15, 2025
72c7c73
get rid of verbose argument when just used for printing
malihass Jul 15, 2025
5bb13af
get rid of verbose argument when possible
malihass Jul 15, 2025
50bd7b4
use logger and exception when possible
malihass Jul 15, 2025
e865ee3
use logger warning and info instead of doing it by hand
malihass Jul 15, 2025
fabda0d
get rid of verbose parameter and use more f strings
malihass Jul 15, 2025
d58fae1
Merge pull request #118 from NREL/logger
malihass Jul 15, 2025
9c72a66
Merge pull request #117 from NREL/failfast
malihass Jul 18, 2025
babb665
Format sim folder
malihass Jul 21, 2025
b4b826e
Merge pull request #120 from NREL/simid
malihass Jul 22, 2025
e1598c5
add tutorial for python interface
malihass Jul 24, 2025
260a427
update refs
malihass Jul 24, 2025
df48ef1
Merge branch 'main' into postprocessdoc
malihass Jul 24, 2025
8c9ec73
remove camelcase and add doc strings for tutorial
malihass Jul 24, 2025
9834d28
add temporary fix for numpyro
malihass Jul 24, 2025
8075078
correct only for specific jax versions
malihass Jul 24, 2025
b097287
Merge pull request #121 from NREL/postprocessdoc
malihass Jul 24, 2025
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
2 changes: 1 addition & 1 deletion .github/linters/.codespellrc
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
[codespell]
skip = None, .git,OFsolvers,tutorial_cases,experimental_cases,build,_build,__pycache__,data_conditional_mean,Figures,assets
skip = None, .git,OFsolvers,*.pdf, tutorial_cases,experimental_cases,build,_build,__pycache__,data_conditional_mean,Figures,assets
ignore-words = .github/linters/.codespell-ignore-words
18 changes: 8 additions & 10 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ jobs:
strategy:
fail-fast: false
matrix:
python-version: ['3.10', '3.11', '3.12']
python-version: ['3.10', '3.13']
os: ['ubuntu-latest', 'macos-latest']
defaults:
run:
Expand All @@ -67,15 +67,8 @@ jobs:
pip install --upgrade pip
pip install .
pip install pytest
- name: Test preprocess
run: |
pytest tests/preprocess
- name: Test mesh
run: |
pytest tests/meshing
- name: Test postprocessing
run: |
pytest tests/postprocess
- name: Test
run: pytest .

Test-pypi-Bird:
name: Test-pypi-BiRD (${{ matrix.python-version }}, ${{ matrix.os }})
Expand Down Expand Up @@ -176,4 +169,9 @@ jobs:
cd tutorial_cases/airlift_40m
bash run.sh
cd ../../
- name: Run flat panel reactor tutorial
run: |
cd tutorial_cases/FlatPanel_250L_ASU
bash run.sh
cd ../../

1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -136,3 +136,4 @@ dmypy.json
*.stl

*.swp
.vim
15 changes: 9 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -47,12 +47,15 @@ To cite BiRD, please use these articles on [CO2 interphase mass transfer](https:


```
@article{hassanaly2025inverse,
title={Bayesian calibration of bubble size dynamics applied to \ce{CO2} gas fermenters},
author={Hassanaly, Malik and Parra-Alvarez, John M. and Rahimi, Mohammad J., Municchi, Federico and Sitaraman, Hariswaran},
journal={Chemical Engineering Research and Design},
year={2025},
}
@article{hassanaly2025bayesian,
title={Bayesian calibration of bubble size dynamics applied to CO2 gas fermenters},
author={Hassanaly, Malik and Parra-Alvarez, John M and Rahimi, Mohammad J and Municchi, Federico and Sitaraman, Hariswaran},
journal={Chemical Engineering Research and Design},
volume={215},
pages={312--328},
year={2025},
publisher={Elsevier}
}

@article{rahimi2018computational,
title={Computational fluid dynamics study of full-scale aerobic bioreactors: Evaluation of gas--liquid mass transfer, oxygen uptake, and dynamic oxygen distribution},
Expand Down
17 changes: 17 additions & 0 deletions applications/sparger_placement_opt.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import os
import pickle
import shutil

import numpy as np

from bird.preprocess.json_gen.design_io import *
from bird.preprocess.json_gen.generate_designs import *

if __name__ == "__main__":

generate_single_scaledup_reactor_sparger_cases(
sparger_locs=[0.3, 0.5, 1.4],
sim_id=0,
vvm=0.4,
study_folder=".",
)
6 changes: 6 additions & 0 deletions bird/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
from bird.version import __version__

BIRD_DIR = os.path.dirname(os.path.realpath(__file__))
BIRD_CASE_DIR = os.path.join(BIRD_DIR, "../tutorial_cases")
BIRD_MESH_DIR = os.path.join(BIRD_DIR, "meshing")
BIRD_POST_DIR = os.path.join(BIRD_DIR, "postprocess")
BIRD_PRE_DIR = os.path.join(BIRD_DIR, "preprocess")
Expand Down Expand Up @@ -34,4 +35,9 @@
)
BIRD_EARLY_PRED_DATA_DIR = os.path.join(BIRD_POST_DIR, "data_early")
BIRD_KLA_DATA_DIR = os.path.join(BIRD_POST_DIR, "data_kla")
BIRD_CASE_GEN_DATA_DIR = os.path.join(BIRD_PRE_DIR, "data_case_gen")
BIRD_INV_DIR = os.path.join(BIRD_DIR, "inverse_modeling")

from bird.logging_config import setup_logging

setup_logging(level="INFO")
7 changes: 5 additions & 2 deletions bird/calibration/param_nn.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import argparse
import logging
import os
import sys
import time
Expand All @@ -13,6 +14,8 @@
from sklearn.preprocessing import MinMaxScaler, StandardScaler
from tensorflow.keras import initializers, layers, optimizers, regularizers

logger = logging.getLogger(__name__)


def flexible_activation(x, activation):
if activation is None:
Expand All @@ -36,7 +39,7 @@ def flexible_activation(x, activation):
elif activation.lower() == "leakyrelu":
out = layers.LeakyReLU()(x)
else:
sys.exit(f"ERROR: unknown activation {activation}")
raise NotImplementedError(f"unknown activation {activation}")
return out


Expand Down Expand Up @@ -185,7 +188,7 @@ def train(
gradient_threshold=None,
):
if gradient_threshold is not None:
print(f"INFO: clipping gradients at {gradient_threshold:.2g}")
logger.info("clipping gradients at {gradient_threshold:.2g}")
# Make sure the control file for learning rate is consistent with main.py, at least at first
self.prepareLog()
bestLoss = None
Expand Down
34 changes: 34 additions & 0 deletions bird/logging_config.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import logging
from pathlib import Path


class ConditionalFormatter(logging.Formatter):
def format(self, record):
"""Change how to log if it is an INFO or a WARNING/ERROR"""
if record.levelno >= logging.WARNING:
self._style._fmt = (
"%(asctime)s [%(levelname)s] %(name)s: %(message)s"
)
else:
self._style._fmt = "%(asctime)s [%(levelname)s] bird: %(message)s"
return super().format(record)


def setup_logging(logfile: str | None = None, level=logging.INFO):
"""Setup logging"""

logger = logging.getLogger()
logger.setLevel(level)

formatter = ConditionalFormatter()

# Console handler
ch = logging.StreamHandler()
ch.setFormatter(formatter)
logger.addHandler(ch)

# Optional file handler
if logfile:
fh = logging.FileHandler(Path(logfile))
fh.setFormatter(formatter)
logger.addHandler(fh)
56 changes: 41 additions & 15 deletions bird/meshing/_mesh_tools.py
Original file line number Diff line number Diff line change
@@ -1,18 +1,46 @@
import json
import logging
import os
import sys
from pathlib import Path

import numpy as np
from ruamel.yaml import YAML

logger = logging.getLogger(__name__)


def parseJsonFile(input_filename):
with open(input_filename) as f:
inpt = json.load(f)
return inpt


def check_for_tabs_in_yaml(file_path: str) -> None:
"""
Checks if a YAML file contains any tab characters.
Raises a ValueError if tabs found.

Parameters
----------
file_path: str
path to yaml filename
"""

with open(file_path, "r", encoding="utf-8") as f:
lines = f.readlines()
for iline, line in enumerate(lines):
if "\t" in line:
raise ValueError(
f"Tab character found on line {iline} of '{file_path}'. "
"YAML files must use spaces for indentation."
)


def parseYAMLFile(input_filename):
if not os.path.exists(input_filename):
raise FileNotFoundError(input_filename)
check_for_tabs_in_yaml(input_filename)
yaml = YAML(typ="safe")
inpt = yaml.load(Path(input_filename))
return inpt
Expand Down Expand Up @@ -85,10 +113,8 @@ def bissection(val, stretch_fun, N1):
resultmin = stretch_fun(Gmin, N1) - val
resultmax = stretch_fun(Gmax, N1) - val
if resultmin * resultmax > 0:
print(
"Error,the initial bounds of grading do not encompass the solution"
)
# stop
logger.error("Initial bounds of grading do not encompass the solution")
sys.exit()

for i in range(1000):
Gmid = 0.5 * (Gmax + Gmin)
Expand Down Expand Up @@ -202,8 +228,8 @@ def verticalCoarsening(
length / deltaE, stretch_fun, NVert[ind]
)
if iterate:
print(
f"WARNING: reduced NVert[{ind}] from {origNVert} to {NVert[ind]}"
logger.warning(
f"reduced NVert[{ind}] from {origNVert} to {NVert[ind]}"
)
block_cell_minus_length[ind] = deltaE
block_cell_plus_length[ind] = deltaE * gradVert[ind]
Expand All @@ -225,8 +251,8 @@ def verticalCoarsening(
length / deltaE, stretch_fun, NVert[ind]
)
if iterate:
print(
f"WARNING: reduced NVert[{ind}] from {origNVert} to {NVert[ind]}"
logger.warning(
f"reduced NVert[{ind}] from {origNVert} to {NVert[ind]}"
)
block_cell_minus_length[ind] = deltaE / gradVert[ind]
block_cell_plus_length[ind] = deltaE
Expand Down Expand Up @@ -316,8 +342,8 @@ def radialCoarsening(
length / deltaE, stretch_fun, NR[ind]
)
if iterate:
print(
f"WARNING: reduced NR[{ind}] from {origNR} to {NR[ind]}"
logger.warning(
f"reduced NR[{ind}] from {origNR} to {NR[ind]}"
)
block_cell_minus_length[ind] = deltaE
block_cell_plus_length[ind] = deltaE * gradR[ind]
Expand All @@ -334,8 +360,8 @@ def radialCoarsening(
length / deltaE, stretch_fun, NR[ind]
)
if iterate:
print(
f"WARNING: reduced NR[{ind}] from {origNR} to {NR[ind]}"
logger.warning(
f"reduced NR[{ind}] from {origNR} to {NR[ind]}"
)
block_cell_minus_length[ind] = deltaE / gradR[ind]
block_cell_plus_length[ind] = deltaE
Expand All @@ -359,9 +385,9 @@ def radialCoarsening(
# if (gradR[last_R] > 2 or gradR[last_R] < 0.5) and abs(
# ratio - 1
# ) <= 1e-12:
# print(
# "WARNING: radial smoothing had to be used because your mesh is very coarse"
# logger.warning(
# "radial smoothing had to be used because your mesh is very coarse"
# )
# print("\tIncrease NS in input file to avoid this warning")
# logger.warning("\tIncrease NS in input file to avoid this warning")

return NR, gradR, minCell, maxCell
10 changes: 3 additions & 7 deletions bird/meshing/_stirred_tank_reactor.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@
from pathlib import Path

import numpy as np
from ruamel.yaml import YAML

from bird.meshing._mesh_tools import parseYAMLFile


class StirredTankReactor:
Expand Down Expand Up @@ -133,11 +134,6 @@ def __init__(
def from_file(cls, yamlfile):
if ".yaml" not in yamlfile:
yamlfile += ".yaml"
if os.path.exists(yamlfile):
yamlpath = Path(yamlfile)
else:
raise FileNotFoundError(yamlfile)
yaml = YAML(typ="safe")
in_dict = yaml.load(yamlpath)
in_dict = parseYAMLFile(yamlfile)
react_dict = {**in_dict["geometry"], **in_dict["mesh"]}
return cls(**react_dict)
20 changes: 11 additions & 9 deletions bird/meshing/block_cyl_mesh.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
import logging
import os
import sys

import numpy as np

from bird.meshing._mesh_tools import *

logger = logging.getLogger(__name__)


def assemble_geom(input_file, topo_file):
# inpt = parseJsonFile(input_file)
Expand Down Expand Up @@ -106,7 +109,6 @@ def assemble_mesh(input_file, geomDict):
),
1,
)
# print(NR)
NS = [NR[0] * 2]
# Now figure out grading of each block
for ir in range(len(R)):
Expand Down Expand Up @@ -189,14 +191,14 @@ def assemble_mesh(input_file, geomDict):
minCellR = np.amin(block_cell_length)
maxCellR = np.amax(block_cell_length)

print("Vertical mesh:")
print(f"\tTotal NVert {sum(NVert)}")
print(f"\tNVert {NVert}")
print(f"\tsize min {minCellVert:.2f}mm max {maxCellVert:.2f}mm")
print("Radial mesh:")
print(f"\tTotal NR {sum(NR)}")
print(f"\tNR {NR}")
print(f"\tsize min {minCellR:.2f}mm max {maxCellR:.2f}mm")
logger.info("Vertical mesh:")
logger.info(f"\tTotal NVert {sum(NVert)}")
logger.info(f"\tNVert {NVert}")
logger.info(f"\tsize min {minCellVert:.2f}mm max {maxCellVert:.2f}mm")
logger.info("Radial mesh:")
logger.info(f"\tTotal NR {sum(NR)}")
logger.info(f"\tNR {NR}")
logger.info(f"\tsize min {minCellR:.2f}mm max {maxCellR:.2f}mm")

return {
"NR": NR,
Expand Down
3 changes: 0 additions & 3 deletions bird/meshing/stirred_tank_mesh.py
Original file line number Diff line number Diff line change
Expand Up @@ -314,9 +314,6 @@ def write_blocks(outfile, react):

outfile.write(");\n")

# print "meshz:",meshz
# print "meshr:",meshr


def write_patches(outfile, react):
inhub_ci = react.inhub_circ
Expand Down
Loading
Loading